缩点 最短路
缩点之后跑最长路就好了,简直就是裸题。
代码:
#include<cctype>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 500005
#define M (N<<2)
#define F inline
using namespace std;
struct edge{ int nxt,to; }ed[M];
int n,m,k,s,p,tp,ti,stk[N],w[N],d[N],q[M];
int h1[N],h2[N],num[N],dfn[N],low[N];
bool f[N],bar[N];
F char readc(){
static char buf[100000],*l=buf,*r=buf;
if (l==r) r=(l=buf)+fread(buf,1,100000,stdin);
return l==r?EOF:*l++;
}
F int _read(){
int x=0; char ch=readc();
while (!isdigit(ch)) ch=readc();
while (isdigit(ch)) x=(x<<3)+(x<<1)+(ch^48),ch=readc();
return x;
}
#define addedge(h,x,y) ed[++k]=(edge){h[x],y},h[x]=k
void Tarjan(int x){
dfn[x]=low[x]=++ti,stk[++tp]=x,f[x]=true;
for (int i=h1[x],v;i;i=ed[i].nxt)
if (!dfn[v=ed[i].to])
Tarjan(v),low[x]=min(low[x],low[v]);
else if (f[v]) low[x]=min(low[x],dfn[v]);
if (low[x]==dfn[x])
for (num[x]=x,f[x]=false;stk[tp+1]!=x;)
num[stk[tp]]=x,f[stk[tp--]]=false;
}
#define C(x) x=(x+1)%M+(x==M)
F int spfa(){
int l=0,r=1,ans=0;
q[1]=num[s],d[num[s]]=w[num[s]];
while (l!=r){
int x=q[C(l)]; f[x]=false;
for (int i=h2[x],v;i;i=ed[i].nxt)
if (d[x]+w[v=ed[i].to]>d[v]){
d[v]=d[x]+w[v];
if (!f[v]) q[C(r)]=v,f[v]=true;
}
}
for (int i=1;i<=n;i++)
if (bar[i]) ans=max(ans,d[num[i]]);
return ans;
}
int main(){
n=_read(),m=_read();
for (int i=1,x,y;i<=m;i++)
x=_read(),y=_read(),addedge(h1,x,y);
for (int i=1;i<=n;i++) w[i]=_read();
s=_read(),p=_read();
for (int i=1;i<=p;i++) bar[_read()]=true;
for (int i=1;i<=n;i++) if (!dfn[i]) Tarjan(i);
for (int x=1;x<=n;x++)
for (int i=h1[x],v;i;i=ed[i].nxt)
if (num[x]!=num[v=ed[i].to])
addedge(h2,num[x],num[v]);
for (int i=1;i<=n;i++)
if (num[i]!=i) w[num[i]]+=w[i];
return printf("%d\n",spfa()),0;
}