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
1 2 2
1 3 2
2 4 1
2 5 1
4 5 3
5 3 4
4 3 2
Sample Output
6
HINT
首先一条路径的异或和可以化为一条1到n的简单路径和一些简单环的异或和
我们首先DFS求出任意一条1到n的简单路径以及图中所有最简单的简单环(环上不存在两个点可以通过环外边直连)
然后在一些数中选出一个子集,使它们与一个给定的数的异或和最大,这就是高斯消元的问题了
利用高斯消元使每一位只存在于最多一个数上 然后贪心求解即可
code:
1 #include<cstdio> 2 #include<iostream> 3 #include<cmath> 4 #include<cstring> 5 #include<algorithm> 6 #define maxn 50005 7 #define maxm 200005 8 using namespace std; 9 typedef long long int64; 10 char ch; 11 int n,m,a,b,tot,now[maxn],son[maxm],pre[maxm],N; 12 int64 val[maxm],f[maxn],A[maxm],c,ans; 13 bool ok,bo[maxn]; 14 void read(int &x){ 15 for (ok=0,ch=getchar();!isdigit(ch);ch=getchar()) if (ch=='-') ok=1; 16 for (x=0;isdigit(ch);x=x*10+ch-'0',ch=getchar()); 17 if (ok) x=-x; 18 } 19 void read(int64 &x){ 20 for (ok=0,ch=getchar();!isdigit(ch);ch=getchar()) if (ch=='-') ok=1; 21 for (x=0;isdigit(ch);x=x*10+ch-'0',ch=getchar()); 22 if (ok) x=-x; 23 } 24 void dfs(int u){ 25 bo[u]=1; 26 for (int p=now[u],v=son[p];p;p=pre[p],v=son[p]) 27 if (!bo[v]) f[v]=f[u]^val[p],dfs(v); 28 else A[++N]=f[u]^f[v]^val[p]; 29 } 30 void put(int a,int b,int64 c){pre[++tot]=now[a],now[a]=tot,son[tot]=b,val[tot]=c;} 31 void gauss(){ 32 int i,j,k; 33 for (i=60,k=1;i>=0;i--){ 34 for (j=k;j<=N&&!(A[j]&(1LL<<i));j++); 35 if (j<=N){ 36 swap(A[k],A[j]); 37 for (j=1;j<=N;j++) if (j!=k&&(A[j]&(1LL<<i))) A[j]^=A[k]; 38 k++; 39 } 40 } 41 N=k-1; 42 } 43 int main(){ 44 read(n),read(m); 45 for (int i=1;i<=m;i++) read(a),read(b),read(c),put(a,b,c),put(b,a,c); 46 dfs(1),gauss(),ans=f[n]; 47 for (int i=1;i<=N;i++) ans=max(ans,ans^A[i]); 48 printf("%lld\n",ans); 49 return 0; 50 }