BZOJ_2115 [Wc2011] Xor 【图上线性基】

一、题目

  [Wc2011] Xor

二、分析

  比较有意思的一题,这里也学到一个结论:$1$到$N$的任意一条路径异或和,可以是一个任意一条$1$到$N$的异或和与图中一些环的异或和组合得到。因为一个数异或自己等于$0$。

  对于这题,需要把所有的简单环先全部求出来,可以用$DFS$,然后用任意一条$1$到$N$的路径和的值与所有简单环的异或的值一起构造线性基(如果有不在路径上的环也没关系,可以走到这个环的位置再回来,相当于到这个环起点的这条路径走了两次,异或一下就抵消了),然后就是求最大值了。

三、AC代码

 1 #include <bits/stdc++.h>
 2 
 3 using namespace std;
 4 #define ll long long
 5 #define Min(a,b) ((a)>(b)?(b):(a))
 6 #define Max(a,b) ((a)>(b)?(a):(b))
 7 const int maxn = 5e4 + 13;
 8 const int MAXL = 60;
 9 
10 struct edge
11 {
12     int to, rev;
13     ll cost;
14     edge(){}
15     edge(int to, ll cost, int rev){
16         this->to = to;
17         this->cost = cost;
18         this->rev = rev;
19     }
20 };
21 vector<edge> G[maxn];
22 ll sum[maxn], ans[maxn<<3], base[MAXL + 2];
23 int cnt;
24 bool flag[maxn];
25 
26 void dfs(int s, int rev)
27 {
28     flag[s] = 1;   
29     for(int i = 0; i < G[s].size(); i++) {
30         edge e = G[s][i];
31         if(rev != i) {
32             if(!flag[e.to]) {
33                 sum[e.to] = sum[s]^e.cost;
34                 dfs(e.to, e.rev);
35             }
36             else {
37                 //记录环的异或值
38                 ans[cnt++] = sum[e.to]^sum[s]^e.cost;
39             }
40         }
41     }
42 }
43 
44 void getbase()
45 {
46     memset(base, 0, sizeof(base));
47     for(int i = 0; i < cnt; i++) {
48         for(int j = MAXL; j >= 0; j--) {
49             if( (ans[i]>>j) & 1) {
50                 if(base[j]) {
51                     ans[i] = ans[i]^base[j];
52                 }
53                 else {
54                     base[j] = ans[i];
55                     for(int k = j - 1; k >= 0; k--)
56                         if( (base[j]>>k) & 1)
57                             base[j] ^= base[k];
58                     for(int k = j + 1; k <= MAXL; k++)
59                         if( (base[k]<<j) & 1)
60                             base[k] ^= base[j];
61                     break;
62                 }
63             }
64         }
65     }
66 }
67 
68 int main()
69 {
70     freopen("input.txt", "r", stdin);
71     int n, m, from, to;
72     ll D;
73     edge e;
74     scanf("%d%d", &n, &m);
75     for(int i = 0; i < m; i++) {
76         scanf("%d%d%lld", &from, &to, &D);
77         G[from].push_back(edge(to, D, G[to].size() ));
78         G[to].push_back(edge(from, D, G[from].size() - 1));
79     }
80     memset(sum, 0, sizeof(sum));
81     memset(flag, 0, sizeof(flag));
82     cnt = 0;
83     dfs(1, -1);
84     getbase();
85     ll Ans = sum[n];
86     for(int i = MAXL; i >= 0; i--) {
87         if(Ans < (Ans^base[i]) )
88             Ans ^= base[i];
89     }
90     printf("%lld\n", Ans);
91     return 0;
92 }

 

posted @ 2019-08-16 22:41  Dybala21  阅读(135)  评论(0编辑  收藏  举报