Codeforces 845G Shortest Path Problem?(异或最短路)

版权声明:转载请注明出处:http://blog.csdn.net/yasola,谢谢 https://blog.csdn.net/Yasola/article/details/77647779

G. Shortest Path Problem?
time limit per test
3 seconds
memory limit per test
512 megabytes
input
standard input
output
standard output

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 and vertex n.

Note that graph can contain multiple edges and loops. It is guaranteed that the graph is connected.

Input

The first line contains two numbers n and m (1 ≤ n ≤ 100000n - 1 ≤ m ≤ 100000) — the number of vertices and the number of edges, respectively.

Then m lines follow, each line containing three integer numbers xy and w (1 ≤ x, y ≤ n0 ≤ w ≤ 108). These numbers denote an edge that connects vertices x and y and has weight w.

Output

Print one number — the minimum length of path between vertices 1 and n.

Examples
input
3 3
1 2 3
1 3 2
3 2 0
output
2
input
2 2
1 1 3
1 2 3
output
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;
}

阅读更多

没有更多推荐了,返回首页