[IOI2008]Island

基环树

找环,环外处理,环上处理

#include
#define re return
#define inc(i,l,r) for(int i=l;i<=r;++i) 
using namespace std;
templateinline void rd(T&x)
{
    char c;bool f=0;
    while((c=getchar())<'0'||c>'9')if(c=='-')f=1;
    x=c^48;
    while((c=getchar())>='0'&&c<='9')x=x*10+(c^48);
    if(f)x=-x;
}

#define ll long long 
const int maxn=1e6+5;
int n,col,k;
bool vis[maxn];
int hd[maxn],du[maxn],c[maxn],q[maxn<<1];
ll f[maxn],d[maxn],a[maxn<<1],b[maxn<<1];
struct node{
    int to,nt,val;
}e[maxn<<1];
inline void add(int x,int y,int z)
{
    e[++k].to=y;e[k].nt=hd[x];hd[x]=k;e[k].val=z;++du[x];
    e[++k].to=x;e[k].nt=hd[y];hd[y]=k;e[k].val=z;++du[y];
}

inline void dfs(int s,int t)
{
    int l,r,i;
    q[l=r=1]=s;c[s]=t;
    while(l<=r)
    {
        for(i=hd[q[l]];i;i=e[i].nt)
        if(!c[e[i].to])
        {
            q[++r]=e[i].to;
            c[e[i].to]=t;
        }
        ++l;
    }
}
inline void topsort()
{
    int l=1,r=0,v,m=0;
    inc(i,1,n)
    if(du[i]==1)q[++r]=i;
    while(l<=r)
    {
        for(int i=hd[q[l]];i;i=e[i].nt)
        if(du[v=e[i].to]>1)
        {
            d[c[v]]=max(d[c[v]],f[q[l]]+f[v]+e[i].val);
            f[v]=max(f[v],f[q[l]]+e[i].val);
            if(--du[v]==1)q[++r]=v;            
        }
        ++l;
    }
}

inline void Get_ans(int t,int x)
{
    if(t==6)
    t=6;
    int l=1,r=0,m=0,y=x,i=1,v;
    while(i)
    {
        du[y]=1;
        for(i=hd[y];i;i=e[i].nt)
        if(du[v=e[i].to]>1)
        {
            y=v;
            a[++m]=f[v];
            b[m]=e[i].val+b[m-1];
            break;
        }
    }
    
    if(m==1)
    {
        for(i=hd[y];i;i=e[i].nt)
        if(e[i].to==x&&e[i].val>b[1])
        b[1]=e[i].val;
        d[t]=max(d[t],f[x]+f[y]+b[1]);
        re ; 
    }
    
    for(i=hd[y];i;i=e[i].nt)
    if(e[i].to==x)
    {a[++m]=f[x];b[m]=e[i].val+b[m-1];break;}
    
    inc(i,m+1,m*2)
    a[i]=a[i-m],b[i]=b[i-1]+b[i-m]-b[i-m-1];
    
    q[l=r=1]=1;
    for(int i=2;i<(m*2);i++)
    {
        while(l<=r&&(i-m)>=q[l])++l;
        d[t]=max(d[t],a[i]+a[q[l]]+b[i]-b[q[l]]);
        while(l<=r&&a[q[r]]-b[q[r]]<=a[i]-b[i])--r;
        q[++r]=i;
    }
}

int main()
{
    int x,y,z;
    rd(n);
    inc(i,1,n)
    {

        rd(x),rd(y);
        add(i,x,y);
    }

    inc(i,1,n)
    if(!c[i])dfs(i,++col);
    topsort();
    
    ll ans=0;
    inc(i,1,n)
    if(du[i]>1&&(!vis[c[i]]))
    {
        vis[c[i]]=1;
        Get_ans(c[i],i);
        ans+=d[c[i]];
    }
    printf("%lld",ans);
    re 0;
}
View Code

 

你可能感兴趣的:([IOI2008]Island)