[BZOJ2115] [Wc2011] Xor

[BZOJ2115] [Wc2011] Xor

Description

Input

第一行包含两个整数N和 M, 表示该无向图中点的数目与边的数目。 接下来M 行描述 M 条边,每行三个整数Si,Ti ,Di,表示 Si 与Ti之间存在 一条权值为 Di的无向边。 图中可能有重边或自环。

Output

仅包含一个整数,表示最大的XOR和(十进制结果),注意输出后加换行回车。

Sample Input

5 7
1 2 2
1 3 2
2 4 1
2 5 1
4 5 3
5 3 4
4 3 2

Sample Output

6

试题分析

一条路径走回来是不产生贡献的。
如果一条边它是割边的话,一定在dfs树中出现。
如果它不是割边的话,一定在若干个环中,所以可以被这些环的异或值所代表。
这样的话我们就随意dfs出一棵dfs树,求出树上1~n路径的异或值,然后把剩下的环(遇到一条返祖边就是形成环)加入线性基。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
//#include<cmath>
#include<algorithm>
 
using namespace std;
#define LL long long
 
inline LL read(){
    LL x=0,f=1; char c=getchar();
    for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
    for(;isdigit(c);c=getchar()) x=x*10+c-'0';
    return x*f;
}
const LL INF = 2147483600;
const LL MAXN = 300010;
 
LL N,M; LL Root[MAXN+1],Next[MAXN<<1],Node[MAXN+1],Cost[MAXN<<1];
LL cnt; inline void insert(LL u,LL v,LL w){
    Node[++cnt]=v; Next[cnt]=Root[u]; Root[u]=cnt; Cost[cnt]=w; return ;
} LL v[MAXN+1];
inline void Add(LL x){
    for(LL i=61;i>=0;i--){
        if((1LL<<i)&x){
            if(!v[i]) {v[i]=x; return;}
            else x=x^v[i]; if(!x) return ;
        }
    } return ;
} LL dis[MAXN+1]; bool vis[MAXN+1];
inline void DFS(LL k,LL va,LL fa){
    dis[k]=va; vis[k]=true; 
    for(LL x=Root[k];x;x=Next[x]){
        LL v=Node[x]; if(v==fa) continue;
        if(vis[v])
            Add(dis[k]^dis[v]^Cost[x]);
        else DFS(v,va^Cost[x],k);
    } return ;
}
inline LL Get_ans(){
    LL ret=dis[N]; for(LL i=61;i>=0;i--){
        if((ret^v[i])>ret) ret=ret^v[i];
    } return ret;
}
 
int main(){
    //freopen(".in","r",stdin);
    //freopen(".out","w",stdout);
    N=read(),M=read();
    for(LL i=1;i<=M;i++){
        LL u=read(),v=read(),w=read();
        insert(u,v,w); insert(v,u,w);
    } DFS(1,0,-1); printf("%lld\n",Get_ans());
    return 0;
}
posted @ 2018-08-27 10:57  wxjor  阅读(110)  评论(0编辑  收藏  举报