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; }