[BZOJ]2115 Xor 线性基

2115: [Wc2011] Xor

Time Limit: 10 Sec   Memory Limit: 259 MB
Submit: 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

Sample Output

6

HINT

Source

[ Submit][ Status][ Discuss]


HOME Back

       随便求一个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);
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值