Bzoj 2115: [Wc2011] Xor

Description

考虑一个边权为非负整数的无向连通图,节点编号为1到N,试求出一条从1号节点到N号节点的路径,使得路径上经过的边的权值的XOR和最大。

路径可以重复经过某些点或边,当一条边在路径上出现了多次时,其权值在计算XOR和时也要被计算相应多的次数,具体见样例。

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

 

题面前面一大堆还有一堆都是说XOR计算是什么(然后我就把那一堆删了....)...首先考虑必须从1开始,到N结束,想到这张图可以是由一条路径和一些环构成,那么就随便找出一条从1到N的路径然后再考虑走环的情况。那就先dfs,记录到这个点的异或值,然后每找到一个搜过的点就两个值异或一下求出走一遍当前环的值,然后把所有环的值插进线性基里,初始值为搜出那条路径上的异或和,然后继续从高到低贪心。因为路径可以被计算多次,所以有环不直接挨着主路径也可以,因为走相同的路径就抵消了。所以这个算法应该是对的...

下面代码:

 

Bzoj 2115: [Wc2011] Xor

 

Description

考虑一个边权为非负整数的无向连通图,节点编号为1到N,试求出一条从1号节点到N号节点的路径,使得路径上经过的边的权值的XOR和最大。

       路径可以重复经过某些点或边,当一条边在路径上出现了多次时,其权值在计算XOR和时也要被计算相应多的次数,具体见样例。

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

 

题面前面一大堆都是说XOR计算是什么...首先考虑必须从1开始,到N结束,想到这张图可以是由一条路径和一些环构成,那么就随便找出一条从1到N的路径然后再考虑走环的情况。那就先dfs,记录到这个点的异或值,然后每找到一个搜过的点就两个值异或一下求出走一遍当前环的值,然后把所有环的值插进线性基里,初始值为搜出那条路径上的异或和,然后继续从高到低贪心。因为路径可以被计算多次,所以有环不直接挨着主路径也可以,因为走相同的路径就抵消了。所以这个算法应该是对的...

下面代码:

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<iostream>
 5 using namespace std;
 6 int head[50010],nxt[200010],whr[200010],cnt=1;
 7 long long val[200010],dis[50010],in[200010],xian[70];
 8 bool vis[50010];
 9 void add(int a,int b,long long v){
10     nxt[cnt]=head[a];
11     whr[cnt]=b;
12     val[cnt]=v;
13     head[a]=cnt++;
14     return;
15 }
16 void dfs(int pos,int pre){
17     vis[pos]=true;
18     for(int i=head[pos];i;i=nxt[i]){
19         int t=whr[i];
20         if(t==pre) continue;
21         if(vis[t]==false){
22             dis[t]=dis[pos]^val[i];
23             dfs(t,pos);
24         }
25         else in[++cnt]=dis[t]^dis[pos]^val[i];
26     }
27 }
28 int main()
29 {
30     int n,m,i,j,a,b;
31     long long v,ans;
32     scanf("%d%d",&n,&m);
33     while(m--){
34         scanf("%d%d%lld",&a,&b,&v);
35         add(a,b,v);add(b,a,v);
36     }
37     cnt=0;
38     dfs(1,1);
39     ans=dis[n];
40     for(i=1;i<=cnt;i++){
41         for(j=60;j>=0;j--){
42             if((in[i]&(1ll<<j))==0) continue;
43             if(xian[j]==0){
44                 xian[j]=in[i];
45                 break;
46             }
47             in[i]^=xian[j];
48         }
49     }
50     for(i=60;i>=0;i--) ans=max(ans,ans^xian[i]);
51     printf("%lld",ans);
52     return 0;
53 }

 

posted @ 2018-02-23 20:19  PnCbf  阅读(81)  评论(0编辑  收藏  举报