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

 

正解:线性基。

又是一道鬼畜的线性基神题。。这是我做的第二道WC的题,也可能将会是我做的代码量最短的WC题。。

我们考虑如何得到答案,首先所有的环都是可以经过的。这是为什么呢?

假设我们从1号点开始走,走到一个环的起点,然后我们经过这个环以后回到了环的起点,这时我们可以直接回到起点。这样,除了环上的路径,其他的路径都被抵消了。那么我们就只选了了这个环,也就是说,任意一个环都是可以选的。

然后我们先把所有的环都选出来,选入线性基中,再选出任意一条从1到n的路径,作为初始ans。初始ans异或线性基的最大值就是我们求的答案。为什么任意选一条路径也是可行的呢?

我们选了一条路径以后,如果存在一条更优的路径,那么这两条路径肯定是构成一个环的,会被选入线性基中。那么我们再用初始的ans异或一下这个环,我们就会发现,初始的ans被抵消了,二更优的那条路径留了下来。所以,我们选一个任意的初始ans是可行的。

于是这道题的实现就很明显了。先找出所有环,构成线性基,然后找出初始ans。这两步显然是可以dfs一遍一起搞的。然后用ans去异或线性基。从高位开始往低位异或。如果当前ans异或这一位的数能使ans变大,那么就异或。最终得到的ans就是我们要求的答案。

所以根据这题,我们还可以得到一个结论:任意一条1到n的路径的异或和,都可以由任意一条1到n的路径的异或和和一些环的异或和来组合得到。

 

 1 //It is made by wfj_2048~
 2 #include <algorithm>
 3 #include <iostream>
 4 #include <complex>
 5 #include <cstring>
 6 #include <cstdlib>
 7 #include <cstdio>
 8 #include <vector>
 9 #include <cmath>
10 #include <queue>
11 #include <stack>
12 #include <map>
13 #include <set>
14 #define inf (1<<30)
15 #define M (100010)
16 #define N (50010)
17 #define il inline
18 #define RG register
19 #define ll long long
20 #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
21 
22 using namespace std;
23 
24 struct edge{ ll nt,to,dis; }g[2*M];
25 
26 ll a[4*M],head[N],vis[N],d[N],p[65],n,m,num,cnt,ans;
27                    
28 il ll gi(){
29     RG ll x=0,q=1; RG char ch=getchar(); while ((ch<'0' || ch>'9') && ch!='-') ch=getchar();
30     if (ch=='-') q=-1,ch=getchar(); while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar(); return q*x;
31 }
32 
33 il void insert(RG ll from,RG ll to,RG ll dis){ g[++num]=(edge){head[from],to,dis},head[from]=num; return; }
34 
35 il void dfs(RG ll x){
36     vis[x]=1;
37     for (RG ll i=head[x],v=g[i].to;i;i=g[i].nt,v=g[i].to){
38     if (!vis[v]) d[v]=d[x]^g[i].dis,dfs(v);
39     else a[++cnt]=d[v]^d[x]^g[i].dis;
40     }
41     return;
42 }
43 
44 il void add(RG ll x){
45     for (RG ll i=62;i>=0;--i)
46     if (x>>i&1){
47         if (!p[i]){ p[i]=x; break; }
48         x^=p[i];
49     }
50     return;
51 }
52 
53 il ll getmax(RG ll x){ RG ll res=x; for (RG ll i=62;i>=0;--i) if (res<(res^p[i])) res^=p[i]; return res; }
54 
55 il void work(){
56     n=gi(),m=gi(); for (RG ll i=1,u,v,w;i<=m;++i) u=gi(),v=gi(),w=gi(),insert(u,v,w),insert(v,u,w);
57     dfs(1); for (RG ll i=1;i<=cnt;++i) add(a[i]); ans=getmax(d[n]); printf("%lld\n",ans); return;
58 }
59 
60 int main(){
61     File("xor");
62     work();
63     return 0;
64 }

 

posted @ 2017-03-14 10:26  wfj_2048  阅读(220)  评论(0编辑  收藏  举报