[关闭]
@xiaoziyao 2020-10-19T18:17:07.000000Z 字数 1086 阅读 1098

CF875F Royal Questions解题报告

未分类


CF875F Royal Questions解题报告:

更好的阅读体验

题意

分析

贪心+并查集妙题

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

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

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

代码

  1. #include<stdio.h>
  2. #include<algorithm>
  3. using namespace std;
  4. const int maxn=200005,maxm=200005;
  5. int n,m,e,ans;
  6. int f[maxn],flg[maxn];
  7. struct edge{
  8. int x,y,z;
  9. }g[maxm];
  10. inline int cmp(edge a,edge b){
  11. return a.z>b.z;
  12. }
  13. int find(int x){
  14. return f[x]==x? x:f[x]=find(f[x]);
  15. }
  16. int main(){
  17. scanf("%d%d",&n,&m);
  18. for(int i=1;i<=m;i++)
  19. scanf("%d%d%d",&g[i].x,&g[i].y,&g[i].z);
  20. sort(g+1,g+1+m,cmp);
  21. for(int i=1;i<=n;i++)
  22. f[i]=i;
  23. for(int i=1;i<=m;i++){
  24. int x=find(g[i].x),y=find(g[i].y);
  25. if(x==y){
  26. if(flg[x]==0)
  27. flg[x]=1,ans+=g[i].z;
  28. continue;
  29. }
  30. if(flg[x]+flg[y]<=1){
  31. f[y]=x,flg[x]=flg[x]+flg[y];
  32. ans+=g[i].z;
  33. }
  34. }
  35. printf("%d\n",ans);
  36. return 0;
  37. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注