Codeforces 845G Shortest Path Problem?(異或最短路)
You are given an undirected graph with weighted edges. The length of some path between two vertices is the bitwise xor of weights of all edges belonging to this path (if some edge is traversed more than once, then it is included in bitwise xor the same number of times). You have to find the minimum length of path between vertex 1
Note that graph can contain multiple edges and loops. It is guaranteed that the graph is connected.
InputThe first line contains two numbers n and m (1 ≤ n ≤ 100000, n - 1 ≤ m ≤ 100000) — the number of vertices and the number of edges, respectively.
Then m lines follow, each line containing three integer numbers x
Print one number — the minimum length of path between vertices 1 and n.
Examples input3 3 1 2 3 1 3 2 3 2 0output
2input
2 2 1 1 3 1 2 3output
0
題目大意:
給你一個無向帶權圖,定義最短路為一條路徑上各條邊的權值異或,求從點1到點N的最短路徑。
解題思路:
首先可以發現對於圖上的路徑異或,環非常特殊。因為無向圖任意一條路徑走過去再原路走回來不會造成任何花費,我們可以把環的花費異或到任意一條路徑上而不需要額外的花費。而且我們可以通過向一條路徑新增和路徑有重複邊的環來改變路徑。
所以我們可以先隨意建立一棵生成樹,同時得到一條1到N的路徑,非生成樹上的邊可以構成環,由於環非常多而且我們通過這個方式也沒有得到的並不是環,只是所有環都可以有它們得到。所以需要利用高斯消元得到線性無關的向量組即可,然後儲存下來。最終列舉把這些向量加到初始路徑上的情況,得到的最小值即為答案。
感覺好像還是講得不是很清楚-_-,附上官方題解:
AC程式碼:
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <string>
#include <ctime>
using namespace std;
#define INF 0x3f3f3f3f
#define ULL unsigned long long
#define LL long long
#define fi first
#define se second
#define P pair<int,bool>
const int MAXV=100000+3;
int V, E;
vector<pair<int, int>> G[MAXV];//圖的鄰接表表示:to, cost
vector<int> circle;//儲存環的花費高斯消元后的線性無關向量組
int dist[MAXV];//生成樹上從根節點到當前結點花費
bool vis[MAXV];
void add(int x)//新增環,並且使每個環的二進位制表示線性無關
{
for(int i=0;i<circle.size();++i)
x=min(x, x^circle[i]);
if(x)
circle.push_back(x);
}
void dfs(int u)//隨意建立一棵生成樹,然後找到環
{
vis[u]=true;
for(int i=0;i<G[u].size();++i)
{
int v=G[u][i].fi;
if(!vis[v])
{
dist[v]=dist[u]^G[u][i].se;
dfs(v);
}
else add(dist[v]^G[u][i].se^dist[u]);
}
}
int main()
{
scanf("%d%d", &V, &E);
for(int i=0;i<E;++i)
{
int u, v, c;
scanf("%d%d%d", &u, &v, &c);
G[u].push_back(make_pair(v, c));
G[v].push_back(make_pair(u, c));
}
dfs(1);
for(int i=0;i<circle.size();++i)//高斯消元,使路徑花費最小
dist[V]=min(dist[V], dist[V]^circle[i]);
printf("%d\n", dist[V]);
return 0;
}