@xiaoziyao
2020-10-19T18:17:07.000000Z
字数 1086
阅读 1098
未分类
贪心+并查集妙题
考虑定义一条有向边的意义为把公主让给了,那么每个点一定入度为,所有的边会形成一个外向基环树森林。
贪心地把公主按照嫁妆从大到小排序,每个公主看成一条无向边,那么可行的方案一定会形成一个基环树森林。
用并查集维护所有王子组成的基环树,用标记来记录一个并查集代表的集合为基环树还是树,然后考虑选择一条边的方法:
#include<stdio.h>
#include<algorithm>
using namespace std;
const int maxn=200005,maxm=200005;
int n,m,e,ans;
int f[maxn],flg[maxn];
struct edge{
int x,y,z;
}g[maxm];
inline int cmp(edge a,edge b){
return a.z>b.z;
}
int find(int x){
return f[x]==x? x:f[x]=find(f[x]);
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
scanf("%d%d%d",&g[i].x,&g[i].y,&g[i].z);
sort(g+1,g+1+m,cmp);
for(int i=1;i<=n;i++)
f[i]=i;
for(int i=1;i<=m;i++){
int x=find(g[i].x),y=find(g[i].y);
if(x==y){
if(flg[x]==0)
flg[x]=1,ans+=g[i].z;
continue;
}
if(flg[x]+flg[y]<=1){
f[y]=x,flg[x]=flg[x]+flg[y];
ans+=g[i].z;
}
}
printf("%d\n",ans);
return 0;
}