1. 程式人生 > >[WC 2011]Xor

[WC 2011]Xor

理解 ins aws 插入 min pan order ack stream

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$號點開始走,走到一個環的起點,然後我們經過這個環以後回到了環的起點,這時我們可以直接回到起點。這樣,除了環上的路徑,其他的路徑都被抵消了。那麽我們就只選了了這個環,也就是說,任意一個環都是可以選的。

然後我們先把所有的環都選出來,選入線性基中,再選出任意一條從$1$到$n$的路徑,作為初始$ans$。初始$ans$異或線性基的最大值就是我們求的答案。為什麽任意選一條路徑也是可行的呢?

我們選了一條路徑以後,如果存在一條更優的路徑,那麽這兩條路徑肯定是構成一個環的,會被選入線性基中。那麽我們再用初始的$ans$異或一下這個環,我們就會發現,初始的$ans$被抵消了,二更優的那條路徑留了下來。所以,我們選一個任意的初始$ans$是可行的。

於是這道題的實現就很明顯了。先找出所有環,構成線性基,然後找出初始$ans$。這兩步顯然是可以$dfs$一遍一起搞的。然後用$ans$去異或線性基。從高位開始往低位異或。如果當前$ans$異或這一位的數能使$ans$變大,那麽就異或。最終得到的$ans$就是我們要求的答案。

補充談談對取出環的異或值的理解:

我們記$d[u]$為從根節點,到$u$節點這條路徑上的$xor$和,那麽假設我們$dfs$拓展路徑的時候,我們找到了以前一個訪問過的點$v$,

那麽這裏就構成了一個環,且由於是$dfs$實現的,很容易知道$d[u]=d[v]⊕w_1⊕w_2⊕...$,$w$為邊權。

我們記我們插入線性基的元素(環上的$xor$和)為$x$,$x=w_1⊕w_2⊕...⊕w_i$,

因為我們知道$a⊕a=0$,那麽$x=d[u]⊕d[u]⊕w_1⊕w_2⊕...⊕w_i$$=d[u]⊕d[v]⊕w_i$($w_i$為$u->v$的邊權)

 1 //It is made by Awson on 2017.9.21
 2 #include <set>
 3 #include <map>
 4 #include <cmath>
 5 #include <ctime> 
 6 #include <queue>
 7 #include <stack>
 8 #include <string>
 9 #include <cstdio>
10 #include <vector>
11 #include <cstdlib>
12 #include <cstring>
13 #include <iostream>
14 #include <algorithm>
15 #define Min(a, b) ((a) < (b) ? (a) : (b))
16 #define Max(a, b) ((a) > (b) ? (a) : (b))
17 #define LL long long
18 using namespace std;
19 const int N = 50000;
20 const int M = 100000;
21 LL st[64];
22 
23 int n, m, u, v;
24 LL c;
25 struct tt {
26     int to, next;
27     LL cost;
28 }edge[2*M+5];
29 int path[N+5], top;
30 LL d[N+5];
31 LL p[64];
32 bool vis[N+5];
33 
34 LL getmax(LL x) {
35     for (int i = 62; i >= 0; i--)
36         if ((x^p[i]) > x)
37             x ^= p[i];
38     return x;
39 }
40 void insert(LL x) {
41     for (int i = 62; i >= 0; i--)
42         if (x&st[i]) {
43             if (!p[i]) {
44                 p[i] = x;
45                 break;
46             }
47             x ^= p[i];
48         }
49 }
50 void add(int u, int v, LL c) {
51     edge[++top].to = v;
52     edge[top].cost = c;
53     edge[top].next = path[u];
54     path[u] = top;
55 }
56 void dfs(int u) {
57     vis[u] = 1;
58     for (int i = path[u]; i; i = edge[i].next) {
59         if (vis[edge[i].to]) insert(d[u]^d[edge[i].to]^edge[i].cost);
60         else {
61             d[edge[i].to] = d[u]^edge[i].cost;
62             dfs(edge[i].to);
63         }
64     }
65 }
66 void work() {
67     st[0] = 1;
68     for (int i = 1; i < 63; i++) st[i] = st[i-1]<<1;
69     for (int i = 1; i <= m; i++) {
70         scanf("%d%d%lld", &u, &v, &c);
71         add(u, v, c); add(v, u, c);
72     }
73     dfs(1);
74     LL ans = getmax(d[n]);
75     printf("%lld\n", ans);
76 }
77 int main() {
78     while (~scanf("%d%d", &n, &m))
79         work();
80     return 0; 
81 }

[WC 2011]Xor