BZOJ 2115: [Wc2011] Xor

来源:互联网 发布:乌鲁木齐seo名录 编辑:程序博客网 时间:2024/06/10 15:34

题目大意:给定一个无向图,每条边上有边权,求一条1到n的路径,使路径上权值异或和最大


首先一条路径的异或和可以化为一条1到n的简单路径和一些简单环的异或和
先DFS求出任意一条1到n的简单路径以及图中所有线性无关的环
然后利用这些环和1-n的简单路径凑出最大的异或和就可以了

#include<bits/stdc++.h>using namespace std;const int N=100010;long long a[N*10],d[N];int head[N],tot,cir=0,vis[N];struct Edge{    int to,next;    long long w;}e[N*2];void init(){    tot=0;    memset(head,-1,sizeof(head));}void addedge(int from,int to,long long w){    e[tot]=(Edge){to,head[from],w};    head[from]=tot++;}void dfs(int u){    vis[u]=1;    for(int i=head[u];i!=-1;i=e[i].next){        int v=e[i].to;        if(vis[v]==1)            a[++cir]=d[u]^d[v]^e[i].w;        else{            d[v]=d[u]^e[i].w;            dfs(v);        }    }}int TOT;void Gauss(int n){    TOT=1;    for(int i=60;i>=0;i--){        for(int j=TOT;j<=n;j++)            if(a[j]&(1LL<<i)){                swap(a[TOT],a[j]);                for(int k=1;k<=n;k++)                    if(k!=TOT&&(a[k]&(1LL<<i)))                        a[k]^=a[TOT];                TOT++;                break;            }    }    --TOT;}int main(){    int n,m,u,v;    long long w;    scanf("%d%d",&n,&m);    init();    for(int i=1;i<=m;i++){        scanf("%d%d%lld",&u,&v,&w);        addedge(u,v,w);        addedge(v,u,w);    }    d[1]=0,dfs(1);    Gauss(cir);    long long ans=d[n];    for(int i=1;i<=TOT;i++)        ans=max(ans,ans^a[i]);    printf("%lld\n",ans);    return 0;}
0 0
原创粉丝点击