【题解】展翅翱翔之时 (はばたきのとき)

sol:

考虑对于每个基环树求答案。

对于一棵树,考虑对于每个点只保留通向它的最大的边。

对于基环树,考虑强行断掉环上的一条边,记录环上点通向它的最大边和次大边,如果最大边都是环上边就必须选择一个点强行断成非环边。

注意特判所有点形成一个环的情况。

#include<bits/stdc++.h> #define ll long long #define inf 0x3f3f3f3f #define fi first #define se second #define db double using namespace std; const int Maxn=1e5+5; int n,m,p[Maxn],cnt,cnt2,a[Maxn],b[Maxn],suf[Maxn],in[Maxn],hua[Maxn],vis[Maxn]; ll tot,res,mx[Maxn],mx2[Maxn]; int head,tail,q[Maxn]; ll loop(int rt) { int f=0; ll tmp=inf,tmp2=0; m=0; p[++m]=rt; for(int i=a[rt];i!=rt;i=a[i]) { p[++m]=i; } for(int i=1;i<=m;i++) { tmp2+=mx[p[i]]; vis[p[i]]=1; if(mx[p[i]]>mx2[p[i]]&&suf[p[i]]==mx[p[i]]) { tmp=min(tmp,mx[p[i]]-mx2[p[i]]); } else { f=1; } } if(f==1) { return tmp2; } else { return tmp2-tmp; } } signed main() { scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d%d",&a[i],&b[i]); tot+=b[i]; in[a[i]]++; if(b[i]>mx[a[i]]) { mx2[a[i]]=mx[a[i]]; mx[a[i]]=b[i]; } else if(b[i]>mx2[a[i]]) { mx2[a[i]]=b[i]; } } for(int i=1;i<=n;i++) hua[i]=1; head=1; for(int i=1;i<=n;i++) { if(in[i]==0) { q[++tail]=i; } } while(head<=tail) { int x=q[head++]; hua[x]=0; if(--in[a[x]]==0) q[++tail]=a[x]; } for(int i=1;i<=n;i++) { if(hua[i]) { suf[a[i]]=b[i]; } } for(int i=1;i<=n;i++) { if(hua[i]&&!vis[i]) { res+=loop(i); cnt++; } else if(!hua[i]) { cnt2++; res+=mx[i]; } } if(cnt==1&&cnt2==0) { printf("0"); return 0; } printf("%lld",tot-res); }

__EOF__

本文作者仰望星空的蚂蚁
本文链接https://www.cnblogs.com/cqbzly/p/17530242.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   仰望星空的蚂蚁  阅读(4)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· DeepSeek 开源周回顾「GitHub 热点速览」
点击右上角即可分享
微信分享提示