本来看到是APIO的题被吓到了(因为APIO2015的题),但是其实读完题之后就会做了=_=,就是一个很傻逼的套路,缩点然后DAG上跑DP做长路。
#include <cmath>
#include <queue>
#include <vector>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define rep(i,x,y) for(int i=(x);i<=(y);i++)
#define repl(i,x,y) for(int i=(x);i<(y);i++)
#define repd(i,x,y) for(int i=(x);i>=(y);i--)
using namespace std;
const int N=5e5+5;
const int Inf=1e9;
int cnt,to[N<<1],nxt[N<<1],head[N];
int n,m,s,p,ans,v[N],id[N],sum[N],dis[N];
int num,scc,top,bel[N],vis[N],dfn[N],low[N],stack[N];
vector<int>ed[N],edge[N];
inline int read() {
int x=0;char ch=getchar();bool f=0;
while(ch>'9'||ch<'0'){if(ch=='-')f=1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return f?-x:x;
}
void ins(int x,int y) {
to[++cnt]=y;nxt[cnt]=head[x];head[x]=cnt;
}
void tarjan(int x) {
dfn[x]=low[x]=++num;vis[x]=1;stack[++top]=x;
for(int i=head[x];i;i=nxt[i]) {
int y=to[i];
if(!dfn[y]) tarjan(y),low[x]=min(low[x],low[y]);
else if(vis[y]) low[x]=min(low[x],dfn[y]);
}
if(dfn[x]!=low[x]) return ;
scc++;
while(true) {
int y=stack[top--];
vis[y]=0;bel[y]=scc;sum[scc]+=v[y];
if(x==y) return ;
}
}
void dp() {
rep(i,0,n) vis[i]=0,dis[i]=-Inf;
queue<int>q;q.push(bel[0]);vis[bel[0]]=1;dis[bel[0]]=0;
while(q.size()) {
int x=q.front();q.pop();vis[x]=0;
repl(i,0,ed[x].size()) {
int y=ed[x][i],z=edge[x][i];
if(dis[y]<dis[x]+z) {
dis[y]=dis[x]+z;
if(!vis[y]) {
vis[y]=1;q.push(y);
}
}
}
}
}
int main() {
n=read(),m=read();
rep(i,1,m) {
int x=read(),y=read();ins(x,y);
}
rep(i,1,n) v[i]=read();
s=read(),p=read();ins(0,s);
rep(i,1,p) id[i]=read();
rep(i,0,n) if(!dfn[i]) tarjan(i);
rep(i,0,n) {
for(int j=head[i];j;j=nxt[j]) {
if(bel[i]!=bel[to[j]]) {
ed[bel[i]].push_back(bel[to[j]]);
edge[bel[i]].push_back(sum[bel[to[j]]]);
}
}
}
dp();
rep(i,1,p) ans=max(ans,dis[bel[id[i]]]);
printf("%d",ans);
return 0;
}