代码源 Div1 - 109#454. Minimum Or Spanning Tree(最小生成树,边权按位或,贪心,并查集) CF1624G
Posted 小哈里
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了代码源 Div1 - 109#454. Minimum Or Spanning Tree(最小生成树,边权按位或,贪心,并查集) CF1624G相关的知识,希望对你有一定的参考价值。
problem
solution
- 题意:生成树的代价为他所有边的边权按位或得到的值,求最小生成树
- 贪心,一般来说,求 按位与 和 按位或 的最大值都可以从高往低逐位的贪心处理
- 对于当前位 b 而言,若存在 n−1 条边的边权都不存在 b 且不构成环的话,那么我们可以把所有包含 b 的边都删除;若不足 n−1 条边满足之前的条件的话,则将 b 加入答案
//AC1
#include<bits/stdc++.h>
using namespace std;
#define ios ios::sync_with_stdio(0), cin.tie(0),cout.tie(0)
typedef long long LL;
const LL maxn = 1e6+10;
int fa[maxn+10];
void init(int n)for(int i = 0; i <= n; i++)fa[i]=i;
int find(int x)return x==fa[x]?x:fa[x]=find(fa[x]);
void merge(int x, int y)x=find(x);y=find(y);if(x!=y)fa[x]=y;
int count(int n)int cnt=0; for(int i = 1; i <= n; i++)if(fa[i]==i)cnt++;return cnt;
struct nodeint u, v, w; e[maxn];
int vis[maxn];
int main()
int n, m; cin>>n>>m;
for(int i = 1; i <= m; i++)
cin>>e[i].u>>e[i].v>>e[i].w;
int ans = 0;
for(int b = 29; b >= 0; b--)
init(n);
int cc = 1;
for(int i = 1; i <= m; i++)
if(vis[i])continue;
if((~e[i].w>>b) & 1)
if(find(e[i].u)!=find(e[i].v))
merge(e[i].u, e[i].v);
cc++;
if(cc == n)
for(int i = 1; i <= m; i++)
if((~e[i].w>>b) & 1)
else
vis[i] = 1;
else
ans |= 1<<b;
cout<<ans<<"\\n";
return 0;
//AC2
#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(0), cin.tie(0),cout.tie(0)
typedef long long LL;
const LL maxn = 1e6+10;
int fa[maxn+10];
void init(int n)for(int i = 1; i <= n; i++)fa[i]=i;
int find(int x)return x==fa[x]?x:fa[x]=find(fa[x]);
void merge(int x, int y)x=find(x);y=find(y);if(x!=y)fa[x]=y;
int count(int n)int cnt=0; for(int i = 1; i <= n; i++)if(fa[i]==i)cnt++;return cnt;
tuple<int,int,int>e[maxn<<1];
int main()
IOS;
int n, m; cin>>n>>m;
for(int i = 1; i <= m; i++)
cin>>get<0>(e[i])>>get<1>(e[i])>>get<2>(e[i]);
int k = 29;
int ans = (1<<k)-1;
for(int i = k-1; i >= 0; i--)
init(n);
int cc = n;
ans ^= (1<<i);
for(int j = 1; j <= m; j++)
if((get<2>(e[j])|ans)==ans && find(get<0>(e[j]))!=find(get<1>(e[j])))
merge(get<0>(e[j]), get<1>(e[j]));
cc--;
ans ^= ((int)(cc!=1)<<i);
cout<<ans<<"\\n";
return 0;
以上是关于代码源 Div1 - 109#454. Minimum Or Spanning Tree(最小生成树,边权按位或,贪心,并查集) CF1624G的主要内容,如果未能解决你的问题,请参考以下文章
代码源 Div1 - 105#451. Dis(倍增求LCA)