bzoj 2115: [Wc2011] Xor 线性基+dfs树

来源:互联网 发布:json格式的字符串 编辑:程序博客网 时间:2024/06/05 13:18

题意

给出一个带权无向图,求一条1到n的路径使得其路径上边权的异或和最大。
n<=50000,m<=100000

分析

把dfs树建出来后,所有边要么是树边要么是非树边。显然我们可以通过走一条反祖边来使我们的答案异或上该返祖边所在环的权值。那么就把所有环的权值扔到线性基里面,最后取个最大的即可。

代码

#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<algorithm>using namespace std;typedef long long LL;const int N=50005;int cnt,n,m,last[N];bool vis[N];LL bas[65],bin[65],dis[N];struct edge{int to,next;LL w;}e[N*4];void addedge(int u,int v,LL w){    e[++cnt].to=v;e[cnt].w=w;e[cnt].next=last[u];last[u]=cnt;    e[++cnt].to=u;e[cnt].w=w;e[cnt].next=last[v];last[v]=cnt;}void ins(LL x){    for (int i=60;i>=0;i--)        if (x&bin[i])        {            if (!bas[i]){bas[i]=x;break;}            x^=bas[i];        }}void dfs(int x,int fa){    vis[x]=1;    for (int i=last[x];i;i=e[i].next)        if (!vis[e[i].to]) dis[e[i].to]=dis[x]^e[i].w,dfs(e[i].to,i);        else if (i!=(fa^1)) ins(dis[x]^dis[e[i].to]^e[i].w);}int main(){    bin[0]=1;    for (int i=1;i<=60;i++) bin[i]=bin[i-1]*2;    scanf("%d%d",&n,&m);cnt=1;    for (int i=1;i<=m;i++)    {        int x,y;LL z;        scanf("%d%d%lld",&x,&y,&z);        addedge(x,y,z);    }    dfs(1,0);    LL ans=dis[n];    for (int i=60;i>=0;i--)        if ((ans^bas[i])>ans) ans^=bas[i];    printf("%lld",ans);    return 0;}