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 }
Bzoj 2115: [Wc2011] Xor