日常刷题2025-3-10
日常刷题2025-3-10
E - Min of Restricted Sum
青色
思路:生成树+按位考虑
充分利用了异或运算可逆性质来连边,外加按位考虑和生成树的一道题。非常具有参考价值。
树一定是无环的,所以做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;
}

浙公网安备 33010602011771号