2115: [Wc2011] Xor
Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 3629 Solved: 1529
[ Submit][ Status][ Discuss]
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
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
Source
随便求一个1-n的路径异或和, 然后我们再记录环的异或和. 因为这个路径随便异或一个环, 就是任意一条路径. 因为假如说有另外一条路径比他更优, 因为都是从1 - n, 那么这两条路径成了环. 异或一下这个环相当于就是选择了另一条路径. 若有部分交集就相当于多个环, 那就异或多个环. 异或一个与当前路径没有交集的环, 相当于就是从1去那个环绕一圈, 然后回到1号点, 再从1-n.
那么 我们把环的异或值一个一个插进线性基里, 从高到低取max即可. 环用dfs求.
#include<stdio.h>
#include<algorithm>
using namespace std;
const int maxn = 50005;
typedef long long dnt;
bool vis[maxn];
int h[maxn], num, n, m, top;
dnt dis[maxn], pw[64], s[maxn * 8], b[64], ans;
inline const dnt read(){
register dnt x = 0;
register char ch = getchar();
while(ch < '0' || ch > '9') ch = getchar();
while(ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
return x;
}
struct edge{ int nxt, v; dnt w;}e[maxn * 4];
inline void add(int u, int v, dnt w){
e[++num].v = v, e[num].w = w, e[num].nxt = h[u], h[u] = num;
e[++num].v = u, e[num].w = w, e[num].nxt = h[v], h[v] = num;
}
void dfs(int u){
vis[u] = true;
for(int i = h[u]; i; i = e[i].nxt){
int v = e[i].v;
if(!vis[v]) dis[v] = dis[u] ^ e[i].w, dfs(v);
else{
dnt x = dis[v] ^ dis[u] ^ e[i].w;
if(x) s[++top] = x;
}
}
}
int main(){
n = read(), m = read();
int x, y; dnt z; pw[0] = 1;
for(int i = 1; i <= 62; ++i) pw[i] = pw[i - 1] << 1;
for(int i = 1; i <= m; ++i) x = read(), y = read(), z = read(), add(x, y, z);
dfs(1), ans = dis[n];
for(int i = 1; i <= top; ++i)
for(int j = 62; j >= 0; --j)
if(s[i] & pw[j]){
if(!b[j]) {b[j] = s[i]; break;}
s[i] ^= b[j];
}
for(int i = 62; i >= 0; --i)
ans = max(ans, ans ^ b[i]);
printf("%lld\n", ans);
}