bzoj1179: [Apio2009]Atm

tatjan缩强连通分量,单源最长路。

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn = 500000 + 10;
const int maxm = 1000000 + 10;

int G[maxn],V[maxm],Next[maxm],Eid;
int g[maxn],v[maxm],next[maxm],eid;
int n,m,S,T,p,cid,sp,vid,res;
int q[maxm],l,r;
int sum[maxn],color[maxn],W[maxn],w[maxn];
int vis[maxn],dfn[maxn],low[maxn];
int s[maxn];
bool inque[maxn],bar[maxn],b[maxn];

void Addedge(int a,int b) {
    V[Eid]=b; Next[Eid]=G[a]; G[a]=Eid++;
}

void addedge(int a,int b) {
    v[eid]=b; next[eid]=g[a]; g[a]=eid++;    
}

void build() {
    memset(G,-1,sizeof(G));
    scanf("%d%d",&n,&m);
    for(int i=1,a,b;i<=m;i++) {
        scanf("%d%d",&a,&b);
        Addedge(a,b);
    }
    for(int i=1;i<=n;i++) scanf("%d",&W[i]);
    scanf("%d%d",&T,&p);
    for(int i=1,a;i<=p;i++) {
        scanf("%d",&a);
        bar[a]=1;
    }
}

void tarjan(int u) {
    vis[u]=1;s[++sp]=u;
    dfn[u]=low[u]=++vid;
    
    for(int i=G[u];~i;i=Next[i]) {
        if(vis[V[i]]==0) {
            tarjan(V[i]);
            low[u]=min(low[u],low[V[i]]);    
        }
        else if(vis[V[i]]==1) {
            low[u]=min(low[u],dfn[V[i]]);
        }
    }
    
    if(dfn[u]==low[u]) {
        ++cid;
        do {
            int t=s[sp];
            color[t]=cid;
            w[cid]+=W[t];
            b[cid]|=bar[t];
            if(t==T) S=cid;
            vis[t]=2;
        } while(s[sp--]!=u);
    }
}

void predo() {
    for(int i=1;i<=n;i++) if(!vis[i]) tarjan(i);    
    memset(g,-1,sizeof(g));
    for(int u=1;u<=n;u++) 
    for(int i=G[u];~i;i=Next[i]) 
        if(color[u]!=color[V[i]])
            addedge(color[u],color[V[i]]);
}

void solve() {
    int u;
    l=r=0; q[r++]=S; sum[S]=w[S];
    while(l<r) {
        u=q[l++]; 
        inque[u]=0;
        if(b[u]) res=max(res,sum[u]);
        for(int i=g[u];~i;i=next[i]) 
            if(sum[v[i]]<sum[u]+w[v[i]]) {
                sum[v[i]]=sum[u]+w[v[i]];    
                if(!inque[v[i]]) 
                    inque[q[r++]=v[i]]=1;
            }
    }
    printf("%d\n",res);
}

int main() {
    build();
    predo();
    solve();    
    return 0;
}
posted @ 2016-05-16 15:40  invoid  阅读(117)  评论(0编辑  收藏  举报