题解:裸的缩点+最短路(DP)
#include<iostream> #include<cstdio> #include<cstring> #include<vector> #include<queue> using namespace std; const int maxn=500009; const int oo=1000000000; int n,m; int v[maxn]; int cntedge; int head[maxn]; int to[maxn<<1],nex[maxn<<1]; void Addedge(int x,int y){ nex[++cntedge]=head[x]; to[cntedge]=y; head[x]=cntedge; } vector<int>G[maxn]; int dfsclock,scccnt; int pre[maxn],lowlink[maxn],sccno[maxn]; int S[maxn],top; void Dfs(int u){ pre[u]=lowlink[u]=++dfsclock; S[++top]=u; for(int i=0;i<G[u].size();++i){ int v=G[u][i]; if(!pre[v]){ Dfs(v); lowlink[u]=min(lowlink[u],lowlink[v]); }else if(!sccno[v]){ lowlink[u]=min(lowlink[u],pre[v]); } } if(lowlink[u]==pre[u]){ ++scccnt; for(;;){ int x=S[top--]; sccno[x]=scccnt; if(x==u)break; } } } int isb[maxn]; int w[maxn]; void Tarjan(){ for(int i=1;i<=n;++i){ if(!pre[i])Dfs(i); } for(int i=1;i<=n;++i)w[sccno[i]]+=v[i]; for(int u=1;u<=n;++u){ for(int i=0;i<G[u].size();++i){ int v=G[u][i]; if(sccno[u]!=sccno[v])Addedge(sccno[u],sccno[v]); } } } int s; queue<int>q; int inq[maxn]; int d[maxn]; void Spfa(){ for(int i=1;i<=scccnt;++i){ d[i]=-oo;inq[i]=0; } d[s]=w[s];inq[s]=1;q.push(s); while(!q.empty()){ int x=q.front();q.pop();inq[x]=0; for(int i=head[x];i;i=nex[i]){ if(d[x]+w[to[i]]>d[to[i]]){ d[to[i]]=d[x]+w[to[i]]; if(!inq[to[i]]){ inq[to[i]]=1; q.push(to[i]); } } } } } int main(){ scanf("%d%d",&n,&m); while(m--){ int x,y; scanf("%d%d",&x,&y); G[x].push_back(y); } for(int i=1;i<=n;++i)scanf("%d",&v[i]); Tarjan(); scanf("%d%d",&s,&m); while(m--){ int x;scanf("%d",&x); isb[sccno[x]]=1; } s=sccno[s]; Spfa(); int ans=-oo; for(int i=1;i<=scccnt;++i){ if(isb[i])ans=max(ans,d[i]); } printf("%d\n",ans); return 0; }