日常刷题2025-3-10

日常刷题2025-3-10

E - Min of Restricted Sum

青色

https://atcoder.jp/contests/abc396/tasks/abc396_e

思路:生成树+按位考虑

充分利用了异或运算可逆性质来连边,外加按位考虑和生成树的一道题。非常具有参考价值。
树一定是无环的,所以做dfs遍历时不会遇到出现过的节点,如果遇到了所明遇到的这条边会出现环,是一条非树边。
https://www.bilibili.com/video/BV1daRYYaEkC/?spm_id_from=333.1007.tianma.2-1-4.click&vd_source=4a339d299e165d8fe38b9926c5240eae

代码

#include <bits/stdc++.h>

typedef std::pair<long long, long long> pll;
typedef std::pair<int, int> pii;
#define INF 0x3f3f3f3f
#define MOD 998244353
using i64 = long long;
const int N = 200200;

int n, m;
std::vector<std::vector<pii>> go(N);
std::vector<bool> vis(N);
std::vector<int> val(N);
std::vector<int> nw;
std::vector<int> ans(N);

void dfs(int cur){
	vis[cur] = 1; nw.push_back(cur);
	for (auto [to, w] : go[cur]){
		if (vis[to]){
			if (val[to]!=(val[cur]^w)){
				std::cout << -1 << '\n';
				exit(0);
			}else{
				continue;
			}
		}
		val[to] = val[cur]^w;
		dfs(to);
	}
}

void solve(){
	std::cin >> n >> m;
	for (int i = 0; i < m; i++){
		int u, v, w; std::cin >> u >> v >> w;
		go[u].push_back({v, w});
		go[v].push_back({u, w});
	}

	for (int i = 1; i <= n; i++){
		if (vis[i]) continue;
		dfs(i);
		int rt = 0;
		for (int j = 30; j >= 0; j--){
			int cnt0 = 0, cnt1 = 0;
			for (auto to : nw){
				if (val[to]&(1<<j)) cnt1++;
				else cnt0++;
			}
			if (cnt1 > cnt0) rt |= (1 << j);
		}
		for (auto to : nw){
			ans[to] = val[to]^rt;
		}
		nw.clear();
	}

	for (int i = 1; i <= n; i++){
		std::cout << ans[i] << ' ';
	}
	std::cout << '\n';
}

signed main()
{
	std::ios::sync_with_stdio(false);
	std::cin.tie(nullptr);
	std::cout<<std::setiosflags(std::ios::fixed)<<std::setprecision(2);
	int t = 1, i;
	for (i = 0; i < t; i++){
		solve();
	}
	return 0;
}
posted @ 2025-03-10 13:06  califeee  阅读(55)  评论(0)    收藏  举报