这题和1093差不多,也就是缩环之后spfa/拓扑排序/记忆化搜索搞一下,多注意一点的就是一个点有酒吧的时候它才能向前更新答案。。
#include<cstdio>
#include<iostream>
#include<memory.h>
#define N 1000005
#define clr(a) memset(a,0,sizeof(a))
using namespace std;
struct edge
{
int e,next;
}ed[N];
int n,m,s,e,p,i,j,ne=0,top=0,t=0,scc,a[N],dfn[N],low[N],belong[N],st[N],ins[N],bar[N],dp[N],v[N];
void add(int s,int e)
{
ed[++ne].e=e;ed[ne].next=a[s];
a[s]=ne;
}
void tarjan(int x)
{
dfn[x]=low[x]=++t;
ins[x]=1;st[++top]=x;
int to;
for (int j=a[x];j;j=ed[j].next)
if (!dfn[to=ed[j].e]) tarjan(to),low[x]=min(low[x],low[to]);
else if (ins[to]) low[x]=min(low[x],dfn[to]);
if (dfn[x]==low[x])
{
++scc;
while (st[top+1]!=x)
{
belong[st[top--]]=scc;
v[scc]+=v[st[top+1]];
ins[st[top+1]]=0;
if (bar[st[top+1]]) bar[scc]=1;
}
}
}
void dfs(int x)
{
dfn[x]=1;
int to;
if (bar[x]) dp[x]=v[x];else dp[x]=0;
for (int j=a[x];j;j=ed[j].next)
{
if (!dfn[to=ed[j].e]) dfs(to);
if (dp[to]) dp[x]=max(dp[x],dp[to]+v[x]);
}
}
int main()
{
freopen("1179.in","r",stdin);
scanf("%d%d",&n,&m);
clr(a);clr(v);
for (i=1;i<=m;i++)
{
scanf("%d%d",&s,&e);
add(s,e);
}
for (i=1;i<=n;i++) scanf("%d",&v[i]);
scanf("%d%d",&s,&p);
clr(bar);
for(i=1;i<=p;i++)
{
scanf("%d",&e);
bar[e]=1;
}
clr(dfn);clr(low);clr(ins);clr(belong);scc=n;
tarjan(s);
for (i=1;i<=n;i++)
for (j=a[i];j;j=ed[j].next)
if (belong[i]&&belong[ed[j].e]&&belong[i]!=belong[ed[j].e]) add(belong[i],belong[ed[j].e]);
dfs(belong[s]);
printf("%d\n",dp[belong[s]]);
}