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

题目意思:

\(n\) 个点,第 \(i\) 点有一条出边 \(i\to a_i\)。更改点 \(x\) 的出边代价为 \(c_x\),要求用最小的代价将所有点连成一个环。

我们先把原图建出来,考虑这张图一定是若干个树连环。

每一个弱连通块一定是类似于这样:

graph.png

即:

iShot2021-07-27 16.22.45

我们的任务则是找到最长的一条链。

对于一条链,每个节点的入度最多为 \(1\)​​,所以,对于树上的点,为了最大化答案,我们选择保留入边中边权最大的一条。

对于环上的点,我们也可以这样做,因为至少去掉的那些边一定不可能被选进最优解中去。

经过这样的处理,还剩下这样的东西:

iShot2021-07-27 16.33.19

这个环是处理的重中之重。

对于环上的一个点,环上与它相邻的点的两条边以及子树的一条边至少会断一条边(没有子树,可以看成有一条边权为 \(0\) 的边)。

我们还发现,我们必须断至少一条环上的边,必须至少保留一条来自子树连向环的边,否则就不为链了。

最后还有一个小细节需要特判一下:

如果这个图本身强联通,答案应为 \(0\)

代码(目前的最优解):

#include<bits/stdc++.h>
#define log(a) cerr<<"\033[32m[DEBUG] "<<#a<<'='<<(a)<<" @ line "<<__LINE__<<"\033[0m"<<endl
#define LL long long
#define SZ(x) ((int)x.size()-1)
#define ms(a,b) memset(a,b,sizeof a)
#define F(i,a,b) for(int i=(a);i<=(b);++i)
#define DF(i,a,b) for(int i=(a);i>=(b);--i)
using namespace std;
inline int read(){char ch=getchar(); int w=1,c=0;
    for(;!isdigit(ch);ch=getchar()) if (ch=='-') w=-1;
    for(;isdigit(ch);ch=getchar()) c=(c<<1)+(c<<3)+(ch^48);
    return w*c;
}
const int N=1e5+10;
int a[N],b[N],h[N],f[N],l[N];
LL ans;
bool vis[N];
queue<int>q;
int main(){
    int n=read();
    F(i,1,n){
        a[i]=read(),b[i]=read();
        h[a[i]]++;
    }
    F(i,1,n)
        if(!h[i])q.push(i);
    if(q.empty()){
        int s=0;
        for(int i=1;!vis[i];i=a[i])s++,vis[i]=true;
        if(s==n){
            puts("0");
            return 0;
        }
    }
    while(q.size()){
        int x=q.front();q.pop();
        if(f[a[x]]){
            ans+=min(f[a[x]],b[x]);
            f[a[x]]=max(f[a[x]],b[x]);
        }else f[a[x]]=b[x];
        if(--h[a[x]]==0)q.push(a[x]);
    }
    F(i,1,n)
        if(h[i]){
            int tot=0;
            for(int j=i;h[a[j]];j=a[j]){
                h[a[j]]=0;
                ans+=f[a[j]];
                l[++tot]=f[a[j]]-b[j];
            }
            sort(l+1,l+tot+1);
            ans-=l[tot];
            DF(i,tot-1,1)
                if(l[i]>0)ans-=l[i];
        }
    cout<<ans;
    return 0;
}
posted @ 2021-10-06 10:34  zhaohaikun  阅读(67)  评论(0编辑  收藏  举报