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

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 }

 

posted @ 2015-07-28 10:55  chenyushuo  阅读(156)  评论(0编辑  收藏  举报