bzoj2115【WC2011】XOR

题意:http://www.lydsy.com/JudgeOnline/problem.php?id=2115

sol  :首先考虑处理出DFS树,那么树上的所有非树边可以构成一个简单环

   因为所有不在1-n的路径上的树边都会被走过去再走回来,对答案无法构成影响

   所以答案即为1-n路径的异或和^(所有环的异或和任选)的最大值

   那么问题转化为从k个数中任选使其异或一个特定的数得异或和最大

   直接跑线性基即可

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#define int long long
using namespace std;
const int Mx=200010;
int n,m,cnt,ans,now,tmp,val[Mx],cir[Mx],vis[Mx];
int tot,head[Mx],nxt[Mx],ver[Mx],cost[Mx];
void add(int x,int y,int z)
{
    nxt[++tot]=head[x];
    ver[tot]=y;
    cost[tot]=z;
    head[x]=tot;
}
void dfs(int x)
{
    vis[x]=1;
    for(int i=head[x];i;i=nxt[i])
    {
        int y=ver[i];
        if(!vis[y])
            val[y]=val[x]^cost[i],dfs(y);
        else
            cir[++cnt]=val[x]^val[y]^cost[i];
    }
}
void gauss()
{
    now=1,m=63;
    while(m--)
    {
        tmp=0; for(int j=now;j<=cnt;j++) if((cir[j]>>m)&1) { tmp=j;break; }
        if(tmp)
        {
            swap(cir[tmp],cir[now]);
            for(int j=1;j<=cnt;j++) if(j!=now&&((cir[j]>>m)&1)) cir[j]^=cir[now];
            now++;
        }
    }
}
signed main()
{
    scanf("%lld%lld",&n,&m);
    for(int i=1,x,y,z;i<=m;i++)
    {
        scanf("%lld%lld%lld",&x,&y,&z);
        add(x,y,z),add(y,x,z);
    }
    dfs(1); gauss(); ans=val[n];
    for(int i=1;i<now;i++) ans=max(ans,ans^cir[i]);
    cout<<ans<<endl;
    return 0;
}

 

posted @ 2017-03-13 15:53  Czarina  阅读(203)  评论(0编辑  收藏  举报