当前位置:   article > 正文

CF1120D(神奇的构造+最小生成树)

cf1120d

考虑把树展开,单独把叶子节点拿出来

于是可以把控制点x的,抽象成是在它叶子节点间连权值为cx的边

显然只用在x子树的最左边的叶子节点和最右边的叶子节点的下一个节点连边(最后一个叶子节点的下一个节点为 n+1),跑最小生成树即可

正确性证明的话,设叶子节点的权值分别为x1,x2xn,做差分yi=xi+1xi,显然i=1nyi=0

正确性的话,感性理解一下吧QAQ,有理有据的感性理解

代码:

  1. //OwO
  2. #include <bits/stdc++.h>
  3. #define N 200010
  4. #define rep(i,x,y) for(i=x;i<=y;++i)
  5. #define add(x,y) g[x].push_back(y)
  6. #define ll long long
  7. #define pii pair<int,int>
  8. using namespace std;
  9. ll c[N];
  10. int dfn[N],sz[N],cnt,tot,fa[N],qwq[N],l[N],r[N],rr[N],n,lf=0;
  11. vector<int> g[N];
  12. struct ed{
  13. int u,v,p;
  14. ll w;
  15. bool operator <(const ed &x)const{ return w<x.w; }
  16. }e[N];
  17. void ADD(int u,int v,int p,ll w){ e[++cnt]=(ed){u,v,p,w}; }
  18. pii dfs(int x,int fa){
  19. pii lst;
  20. int pl=0;
  21. if(g[x].size()<=1 && x!=1) l[x]=r[x]=++lf;
  22. for(int i=0;i<g[x].size();++i){
  23. int to=g[x][i];
  24. if(to!=fa){
  25. pii tmp=dfs(to,x);
  26. l[x]=min(l[x],tmp.first);
  27. r[x]=max(r[x],tmp.second);
  28. }
  29. }
  30. return make_pair(l[x],r[x]);
  31. }
  32. int find(int x){ return (fa[x]==x)?x:fa[x]=find(fa[x]); }
  33. ll solve1(){
  34. int i;ll ans=0;
  35. rep(i,1,cnt){
  36. int u=find(e[i].u),v=find(e[i].v);
  37. if(u==v) continue;
  38. if(u>v) swap(u,v);
  39. fa[v]=u;
  40. ans+=e[i].w;
  41. }
  42. return ans;
  43. }
  44. void solve2(){
  45. int i,nxt,j;tot=0;
  46. rep(i,1,n+1) fa[i]=i;
  47. for(i=1;i<=cnt;i=nxt){
  48. for(j=i;e[j].w==e[i].w;++j){
  49. int u=find(e[j].u),v=find(e[j].v);
  50. if(u!=v) qwq[++tot]=e[j].p;
  51. }
  52. nxt=j;
  53. for(j=i;e[j].w==e[i].w;++j){
  54. int u=find(e[j].u),v=find(e[j].v);
  55. if(u>v) swap(u,v);
  56. if(u!=v) fa[v]=u;
  57. }
  58. }
  59. }
  60. int main(){
  61. int i,x,y;
  62. scanf("%d",&n);
  63. rep(i,1,n) scanf("%I64d",&c[i]),fa[i]=i;fa[n+1]=n+1;
  64. rep(i,1,n-1){
  65. scanf("%d%d",&x,&y);
  66. add(x,y),add(y,x);
  67. }
  68. memset(l,0x3f,sizeof(l));
  69. memset(r,0,sizeof(r));
  70. dfs(1,0);rr[1]=n+1;
  71. rep(i,1,n) ADD(l[i],r[i]+1,i,c[i]);
  72. sort(e+1,e+cnt+1);
  73. cout<<solve1()<<" ";
  74. solve2();
  75. sort(qwq+1,qwq+tot+1);
  76. cout<<tot<<endl;
  77. rep(i,1,tot) printf("%d ",qwq[i]);
  78. }

转载于:https://www.cnblogs.com/PsychicBoom/p/10597099.html

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop】
推荐阅读
  

闽ICP备14008679号