1. 程式人生 > >Bzoj 2115: [Wc2011] Xor

Bzoj 2115: [Wc2011] Xor

必須 can 表示 com bubuko post 一個 後繼 都是

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 }

Bzoj 2115: [Wc2011] Xor