题解 CF875F 【Royal Questions】

· · 题解

CF875F Royal Questions解题报告:

更好的阅读体验

题意

分析

贪心+并查集妙题

考虑定义一条有向边u\rightarrow v的意义为u把公主让给了v,那么每个点一定入度为1,所有的边会形成一个外向基环树森林。

贪心地把公主按照嫁妆从大到小排序,每个公主看成一条无向边,那么可行的方案一定会形成一个基环树森林。

用并查集维护所有王子组成的基环树,用标记flg来记录一个并查集代表的集合为基环树还是树,然后考虑选择一条边的方法:

代码

#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;
}