传送门
用tarjan缩点后在DAG上跑一个SPFA最长路即可,数组有点多,该赋初值一定要赋初值。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<stack>
#include<queue>
#include<vector>
using namespace std;
const int maxn=500002;
int head[maxn],edge=0,n,m,source,P;
int val[maxn];
int pub[maxn],dfn[maxn],low[maxn],ins[maxn],belong[maxn];
int alc[maxn],sum[maxn],dis[maxn],scc=0,cnt=0;
struct EDGE {
int u,v,nxt;
}e[maxn];
stack<int> S;
vector<int> G[maxn];
inline int read() {
int x=0;char c=getchar();
while (c<'0'||c>'9') c=getchar();
while (c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
return x;
}
inline void adde(int u,int v) {
e[edge].nxt=head[u],e[edge].u=u,e[edge].v=v,head[u]=edge++;
}
void dfs(int p) {
dfn[p]=low[p]=++cnt;
ins[p]=1;
S.push(p);
for (int i=head[p];~i;i=e[i].nxt) {
int v=e[i].v;
if (!dfn[v]) {
dfs(v);
low[p]=min(low[p],low[v]);
}
else if (ins[v])
low[p]=min(low[p],dfn[v]);
}
if (low[p]==dfn[p]) {
sum[++scc]=alc[scc]=0;
while (!S.empty()) {
int t=S.top();
S.pop();
ins[t]=0,belong[t]=scc,sum[scc]+=val[t];
if (t==source) source=scc;
if (pub[t]) alc[scc]=1;
if (t==p) break;
}
}
}
void tarjan() {
for (register int i=1;i<=n;++i)
if (!dfn[i]) dfs(i);
for (register int i=0;i<edge;++i) {
int u=belong[e[i].u],v=belong[e[i].v];
if (u!=v) G[u].push_back(v);
}
}
inline void spfa(int source) {
queue<int> q;
bool inq[maxn];
memset(inq,false,sizeof(inq));
memset(dis,-1,sizeof(dis));
inq[source]=1,dis[source]=sum[source];
q.push(source);
while (!q.empty()) {
int p=q.front(),siz=G[p].size();
q.pop(),inq[p]=false;
for (int j=0;j<siz;++j) {
int v=G[p][j];
if (dis[v]<dis[p]+sum[v]) {
dis[v]=dis[p]+sum[v];
if (!inq[v]) {
inq[v]=true;
q.push(v);
}
}
}
}
int ans=0;
for (int i=1;i<=scc;++i)
if (alc[i]) ans=max(ans,dis[i]);
printf("%d\n",ans);
}
int main() {
// freopen("bzoj 1179.in","r",stdin);
memset(head,-1,sizeof(head));
n=read(),m=read();
while (m--) {
int u,v;
u=read(),v=read();
adde(u,v);
}
for (register int i=1;i<=n;++i) val[i]=read(),G[i].clear(),dfn[i]=pub[i]=0;
source=read(),P=read();
while (P--) pub[read()]=1;
tarjan();
spfa(source);
// for (int i=1;i<=scc;++i) printf("%d:%d\n",i,sum[i]);
// for (register int i=1;i<=n;++i) printf("%d:%d\n",i,belong[i]);
return 0;
}