【洛谷P3651】展翅翱翔之时

难以吐槽出题人的中二病……

这题有点类似ZJOI2008 骑士,先跑树上的,最后拆环即可。

#include<bits/stdc++.h>
#define N 100005
typedef long long ll;
using namespace std;
struct Edge{int u,v,next;}G[N<<1];
int head[N],tot=0,vis[N],c[N],q[N],top=0,s[N],n,cnt;
ll sum;
inline void addedge(int u,int v){
    G[++tot].u=u;G[tot].v=v;G[tot].next=head[u];head[u]=tot;
}
void dfs(int u){
    vis[u]=1;q[++top]=u;s[u]=1;
    int mv=0,mst=0,mn=0;ll ret=0;
    for(int i=head[u];i;i=G[i].next){
        int v=G[i].v;ret+=c[v];
        if(c[v]>mn){c[mv]=0;mst=mn;mn=c[v];c[v]-=mst;mv=v;}
        else{if(c[v]>mst){mst=c[v];c[mv]=mn-mst;}c[v]=0;}
    }
    ret-=mn;
    for(int i=head[u];i;i=G[i].next){
        int v=G[i].v;
        if(s[v]){
            int minv=(1<<30);
            if(v==1&&top==n){puts("0");exit(0);}
            for(int i=top;;i--){
                minv=min(minv,c[q[i]]);
                if(q[i]==v)break;
            }
            ret+=minv;
        }
        else if(!vis[v])dfs(v);
    }
    sum+=ret;--top;s[u]=0;
}
inline int read(){
    int f=1,x=0;char ch;
    do{ch=getchar();if(ch=='-')f=-1;}while(ch<'0'||ch>'9');
    do{x=x*10+ch-'0';ch=getchar();}while(ch>='0'&&ch<='9');
    return f*x;
}
int main(){
    n=read();
    for(int i=1;i<=n;i++){int v=read(),cc=read();addedge(v,i);c[i]=cc;}
    for(int i=1;i<=n;i++)if(!vis[i])dfs(i);
    cout<<sum<<endl;
}

 

posted @ 2017-06-23 10:17  zcysky  阅读(382)  评论(0编辑  收藏  举报