icpc 21沈阳B题 Bitwise Exclusive-OR Sequence

原题链接

知道两数的异或值,等价于知道两数二进制下的每位是否相等
那么知道了其中一个值,另一个也唯一确定;如果把所有关系建图,那么只要知道某个结点的权值,同一个连通块内的其他点权也唯一确定

进行两次dfs,第一次判断是否合法,第二次按位黑白染色,将较少的颜色所在位赋为1即可

#include<bits/stdc++.h>
using namespace std;

const int N = 2e5 + 10;

int head[N], idx;
int vis[N];
int clr[N][31], cnt[3];

struct NODE {
	int to, next, w;
} eg[N << 1];

void add(int u, int v, int w) {
	eg[idx].to = v;
	eg[idx].w = w;
	eg[idx].next = head[u];
	head[u] = idx++;
}

void dfs_1(int u, int now) {
	vis[u] = now; // 当前结点赋值 
	for (int i = head[u]; ~i; i = eg[i].next) {
		int v = eg[i].to;
		if (vis[v] == -1) dfs_1(v, now ^ eg[i].w); // 如果没有被访问,就直接进入 
		else if (vis[v] != (now ^ eg[i].w)) { // 确定了一个值,同一个连通块的所有值都唯一确定,如果有冲突肯定非法 
			cout << -1 << "\n"; 
			exit(0);
		}
	}
}

void dfs_2(int u, int now, int p) {
	clr[u][p] = now; // 当前结点染色 
	cnt[now]++; 
	
	for (int i = head[u]; ~i; i = eg[i].next) {
		int v = eg[i].to;
		if (!clr[v][p]) {
			if (eg[i].w >> p & 1) dfs_2(v, 3 - now, p); // 如果边权的当前位是1,那么两个结点的当前位不同 
			else dfs_2(v, now, p); // 反之相等 
		} 
	}
}

void work() {
	memset(vis, -1, sizeof vis);
	memset(head, -1, sizeof head);
	
	int n, m;
	cin >> n >> m;
	
	while (m--) {
		int u, v, w;
		cin >> u >> v >> w;
		add(u, v, w), add(v, u, w); // 连双向边,权值为w 
	}
	
	long long res = 0;
	for (int i = 1; i <= n; i++) if (vis[i] == -1) dfs_1(i, 0); // 如果之前没有被访问,就dfs判断是否合法 
	for (int i = 1; i <= n; i++) { // 第二次dfs统计答案 
		if (!clr[i][0]) { // 如果没有被染色 
			for (int j = 0; j <= 30; j++) {
				cnt[1] = cnt[2] = 0; // 记录黑白颜色的数量 
				dfs_2(i, 1, j); // 黑白染色 
				res += 1ll * min(cnt[1], cnt[2]) * (1 << j); // 取其中较少的 
			}
		}
	}
	
	cout << res << "\n";
}

int main() {
	ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
	int test = 1;
	
	while (test--) work();
	
	return 0;
}
posted @ 2022-10-18 17:52  xhy666  阅读(157)  评论(0)    收藏  举报