HYSBZ - 2115 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

                进行dfs,把图中所有的环找出来进行线性基的插入,之后我们我们的答案就是我们最忌得到的一条1-n的路和这些环的值异或就好了(就是相当于从此条路上跑到环上转一圈再原路返回,收到的变化只有环上的)。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn = 50005;
class BASE {
	static const int DEG = 62;
public:	
	int tot = 0, n = 0;
	ll d[63], nd[63];
	BASE() {
		memset(d, 0, sizeof d);
		tot = 0; n = 0;
	}
	~BASE(){}
	void Init() {
		memset(d, 0, sizeof d);
		tot = 0; n = 0;
	}
	void Ins(ll x) {
		n++;
		for (int i = DEG; i >= 0; i--) {
			if (!(x&(1LL << i)))continue;
			if (!d[i]) { d[i] = x; break; }
			x ^= d[i];
		}
	}
	ll Max(ll x) {
		ll res = x;
		for (int i = DEG; i >= 0; i--) {
			res = max(res, res^d[i]);
		}
		return res;
	}
	ll Min() {
		for (int i = 0; i <= DEG; i++)
			if (d[i])
				return d[i];
		return 0;
	}
	void Rebuild() {
		for (int i = DEG; i >= 0; i--) {
			if (d[i] == 0)continue;
			for (int j = i - 1; j >= 0; j--) {
				if (d[j] == 0)continue;
				if (d[i] & (1LL << j)) d[i] ^= d[j];
			}
		}
		for (int i = 0; i <= DEG; i++)
			if (d[i]) nd[tot++] = d[i];
	}
	ll Kth(ll k) {
		if (k == 1LL && tot < n)return 0;
		if (tot < n)k--;
		if (k >= (1LL << tot)) return -1;
		ll res = 0;
		for (int i = DEG; i >= 0; i--)
			if (k&(1LL << i))
				res ^= nd[i];
		return res;
	}
	void merge(BASE T) {//不一定对~~hh还没题目实践
		for (int i = DEG; i >= 0; i--) {
			if (T.d[i] == 0)continue;
			Ins(T.d[i]);
		}
	}
};
BASE res;
struct fuck{
	int u, v, ne; ll w;
}ed[maxn * 4];
int head[maxn], cnt = 0, vis[maxn]; ll d[maxn];
void add(int u, int v, ll w) {
	ed[cnt].v = v; ed[cnt].u = u;
	ed[cnt].w = w; ed[cnt].ne = head[u]; head[u] = cnt++;
}
void dfs(int u) {
	vis[u] = 1;
	for (int i = head[u]; ~i; i = ed[i].ne) {
		int v = ed[i].v;
		if (vis[v]) {
			res.Ins(d[u] ^ ed[i].w^d[v]);
		}
		else d[v] = d[u] ^ ed[i].w, dfs(v);
	}
}
int main() {
	int n, m; res.Init();
	ios::sync_with_stdio(0);
	cin.tie(0); cout.tie(0);
	cin >> n >> m;
	for (int i = 0; i <= n; i++)
		head[i] = -1, vis[i] = 0;
	d[1] = 0;
	while (m--) {
		int a, b; ll c;
		cin >> a >> b >> c;
		add(a, b, c);
		add(b, a, c);
	}
	dfs(1);
	cout << res.Max(d[n]) << "\n";
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值