tarjan 缩点,跑个最长路。
#include <vector>
#include <iostream>
#include <cstdio>
#include <queue>
#include <cstring>
using namespace std;
const int N=500005;
vector<int>G[N],V[N];
int n,m,ecnt,head[N],val[N],S,p,tim,dfn[N],low[N],stk[N],top,sum[N],col[N],cnt,dis[N];
bool inq[N],vis[N];
struct Edge{int to,nxt,val;}e[N<<1];
void add(int bg,int ed) {e[++ecnt].nxt=head[bg];e[ecnt].to=ed;head[bg]=ecnt;}
void tarjan(int x) {
low[x]=dfn[x]=++tim;inq[x]=1;stk[++top]=x;
for(int i=head[x];i;i=e[i].nxt) {
int v=e[i].to;
if(!dfn[v]) {
tarjan(v);low[x]=min(low[v],low[x]);
}
else if(inq[v]) low[x]=min(low[x],dfn[v]);
}
if(dfn[x]==low[x]) {
++cnt;
int k;
do{
k=stk[top--];
col[k]=cnt;
inq[k]=0;
sum[cnt]+=val[k];
}while(k!=x);
}
}
void spfa() {
memset(dis,0x3f,sizeof dis);
queue<int>q;
q.push(col[0]);
dis[col[0]]=0;vis[col[0]]=1;
while(!q.empty()){
int u=q.front();q.pop();vis[u]=0;
for(int i=0;i<G[u].size();i++){
int v=G[u][i];
if(dis[v]>dis[u]+V[u][i]) {
dis[v]=dis[u]+V[u][i];
if(!vis[v]) vis[v]=1,q.push(v);
}
}
}
}
int main() {
scanf("%d%d",&n,&m);
for(int i=1,u,v;i<=m;i++) {
scanf("%d%d",&u,&v);
add(u,v);
}
for(int i=1;i<=n;i++) scanf("%d",&val[i]);
scanf("%d%d",&S,&p);
int id[N];
for(int i=1;i<=p;i++) scanf("%d",&id[i]);
add(0,S);
for(int i=0;i<=n;i++) if(!dfn[i]) tarjan(i);
for(int i=0;i<=n;i++) {
for(int j=head[i];j;j=e[j].nxt) {
int v=e[j].to;
if(col[v]!=col[i]) G[col[i]].push_back(col[v]),V[col[i]].push_back(-sum[col[v]]);
}
}
spfa();
int ans=0;
for(int i=1,b;i<=p;i++) ans=max(ans,-dis[col[id[i]]]);
cout<<ans;
}