Loading

BZOJ 2115:Xor(线性基+DFS)

题目链接

题意

中文题意

思路

因为存在环和重边,边来回走是没有意义的,因此最终的答案应该是一条从1到n的路径权值异或上若干个环的权值,那么难点在于如何选取这些环的权值使得最终的答案更优。

使用到线性基的贪心算法来计算。DFS处理出环的异或值,然后将这些值加入到线性基中,贪心选取。

参考

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int, int> pii;
const int INF = 0x3f3f3f3f;
const int N = 5e4 + 11;
struct Edge {
	int v, nxt;
	LL w;
} edge[N*4];
int n, m, head[N], vis[N], cnt, tot;
LL p[70], ans, cir[N*4], dis[N];

void Add(int u, int v, LL w) {
	edge[tot] = (Edge) { v, head[u], w }; head[u] = tot++;
	edge[tot] = (Edge) { u, head[v], w }; head[v] = tot++;
}

void dfs(int u) {
	for(int i = head[u]; ~i; i = edge[i].nxt) {
		int v = edge[i].v; LL w = edge[i].w;
		if(vis[v]) cir[++cnt] = dis[v] ^ dis[u] ^ w;
		else vis[v] = 1, dis[v] = dis[u] ^ w, dfs(v);
	}
}

int main() {
	scanf("%d%d", &n, &m);
	memset(head, -1, sizeof(head));
	ans = cnt = tot = 0;
	for(int i = 1; i <= m; i++) {
		int u, v; LL w;
		scanf("%d%d%lld", &u, &v, &w);
		Add(u, v, w);
	}
	memset(p, 0, sizeof(p));
	memset(vis, 0, sizeof(vis));
	vis[1] = 1; dfs(1);
    for(int i = 1; i <= cnt; i++) {
        for(int j = 63; j >= 0; j--) {
            if(((cir[i] >> j) & 1) == 0) continue;
            if(!p[j]) { p[j] = cir[i]; break; }
            cir[i] ^= p[j];
        }
    } ans = dis[n];
    for(int i = 63; i >= 0; i--)
        if((ans ^ p[i]) > ans) ans ^= p[i];
	printf("%lld\n", ans);
	return 0;
}
posted @ 2017-10-10 18:13  Shadowdsp  阅读(207)  评论(0编辑  收藏  举报