记录编号 23536 评测结果 AAAAAAAAAAAAAAAAAAAA
题目名称 [IOI 2008] 岛屿 最终得分 100
用户昵称 Gravatar王者自由 是否通过 通过
代码语言 C++ 运行时间 2.329 s
提交时间 2011-03-14 21:09:25 内存使用 103.26 MiB
显示代码纯文本
#include <stdio.h>
#include <string.h>
#define N 1000010
#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)<(y)?(x):(y))
#define FOR(i,l,r) for (int i=l;i<=r;++i)

int u[N*2],v[N*2],next[N*2],fir[N],pg=1;
int p[N],q[N*2],l[N*2],len,head,tail,n;
int vis[N],flag;
long long f[N],w[N*2],b[N*2],c[N*2],ans_b,ans;

void add(int _u,int _v,int _w) {
    ++pg; u[pg]=_u; v[pg]=_v; w[pg]=_w; next[pg]=fir[_u]; fir[_u]=pg;
    ++pg; u[pg]=_v; v[pg]=_u; w[pg]=_w; next[pg]=fir[_v]; fir[_v]=pg;
}

int bfs(int from) {
    head=0; tail=0; int cir=0;
    q[tail]=from; vis[from]=flag;
    while (head<=tail) {
        int now=q[head++];
        for (int j=fir[now];j;j=next[j]) 
            if (vis[v[j]]!=flag)
                vis[v[j]]=flag ,p[v[j]]=j ,q[++tail]=v[j];
            else if (p[now]!=(j^1)) cir=j;
    }
    return cir;
}

void dp(int from) {
    bfs(from);
    while (tail>=0) {
        int i=q[tail]; long long&res=f[i];
        for (int j=fir[i];j;j=next[j]) if (p[v[j]]==j) {
            long long now=f[i]+f[v[j]]+w[j];
            if (now>ans_b) ans_b=now;
            if (f[v[j]]+w[j]>res) res=f[v[j]]+w[j];
        }
        --tail;
    }
}

void get_cir(int from) {
    ++flag;
    int i,c=bfs(from);
    
    ++flag; for (i=u[c];i;i=u[p[i]]) vis[i]=flag;
    ++flag; len=N;
    for (i=v[c];vis[i]!=flag-1;i=u[p[i]])
        vis[i]=flag, --len, l[len]=i, b[len]=w[p[i]];
    --len; l[len]=i; vis[i]=flag;
    
    memmove(l,&l[len],(N-len)*sizeof(int));
    memmove(b,&b[len],(N-len)*sizeof(long long));
    len=N-len; int t=len;
    
    for (i=u[c];vis[i]!=flag;i=u[p[i]])
        l[len]=i, b[++len]=w[p[i]];
    b[0]=b[len]; b[t]=w[c];
}

int main() {
    freopen("isl.in","r",stdin);
    freopen("isl.out","w",stdout);
    scanf("%d",&n);
    
    FOR(u,1,n) {int v,w; scanf("%d%d",&v,&w); add(u,v,w);}
    
    FOR(from,1,n) if (!vis[from]) {
        get_cir(from);
        ++flag; FOR(i,0,len-1) vis[l[i]]=flag,p[l[i]]=0;
        
        ans_b=0;
        FOR(i,0,len-1) {dp(l[i]);c[i]=f[l[i]];}
        
        memcpy(&b[len],b,len*sizeof(long long));
        memcpy(&c[len],c,len*sizeof(long long));
        FOR(i,1,len*2-1) b[i]+=b[i-1];
        long long temp;
        FOR(i,0,len*2-1) {
            temp=c[i]-b[i];
            c[i]+=b[i]; b[i]=temp;
        }
        
        head=0; tail=-1;
        FOR(i,0,len*2-1) {
            if (i>=len) {
                while (head<=tail && q[head]<=i-len) ++head;
                temp=b[q[head]]+c[i];
                if (temp>ans_b) ans_b=temp;
            }
            while (head<=tail && b[i]>b[q[tail]]) --tail;
            q[++tail]=i;
        }
        ans+=ans_b;
    }
    printf("%lld\n",ans);
}