题目戳这里:http://www.lydsy.com/JudgeOnline/problem.php?id=1179
这道题是一道大水题,直接tarjan缩点合并信息后,跑一边最大的spfa就可以A了。
详细代码:
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
#define del(a,b) memset(a,b,sizeof(a))
#define N 500005
#define inf 0x7fffffff
using namespace std;
int num,head[N],V[N],aa[N],head1[N],num1;
struct Edge{
int v,next;
};
Edge e[2*N],E[2*N];
void adde(int i,int j){
e[++num].v=j;
e[num].next=head[i];
head[i]=num;
}
void add(int i,int j){
E[++num1].v=j;
E[num1].next=head1[i];
head1[i]=num1;
}
int n,m,a,b,dfn[N],low[N],idc,st[N],top,ins[N],belong[N],cnt;
void tarjan(int u){
dfn[u]=low[u]=++idc;
st[++top]=u;ins[u]=1;
for(int i=head[u];i;i=e[i].next){
int v=e[i].v;
if(!dfn[v]){
tarjan(v);
low[u]=min(low[u],low[v]);
}else if(ins[v]) low[u]=min(low[u],dfn[v]);
}
if(dfn[u]==low[u]){
cnt++;
while(st[top+1]!=u){
int x=st[top--];
ins[x]=0;
belong[x]=cnt;
V[cnt]+=aa[x];
}
}
}
int dis[N],s,p[N],P,x,vis[N];
void spfa(){
del(dis,0);
dis[belong[s]]=V[belong[s]];
queue<int>q;
q.push(belong[s]);
while(!q.empty()){
int u=q.front();q.pop();vis[u]=0;
for(int i=head1[u];i;i=E[i].next){
int v=E[i].v;
if(dis[v]<dis[u]+V[v]){
dis[v]=dis[u]+V[v];
if(!vis[v]){
q.push(v);
vis[v]=1;
}
}
}
}
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
scanf("%d%d",&a,&b);
adde(a,b);
}
for(int i=1;i<=n;i++)
scanf("%d",&aa[i]);
for(int i=1;i<=n;i++)
if(!dfn[i])tarjan(i);
scanf("%d%d",&s,&P);
for(int i=1;i<=P;i++){
scanf("%d",&x);
p[i]=belong[x];
}
for(int u=1;u<=n;u++){
for(int i=head[u];i;i=e[i].next){
int v=e[i].v;
if(belong[u]!=belong[v])
add(belong[u],belong[v]);
}
}
spfa();
int ans=0;
for(int i=1;i<=P;i++)
ans=max(ans,dis[p[i]]);
printf("%d\n",ans);
return 0;
}