题目大意:给定一个有向图,每个点上有正权,求一条从起点出发到任意终点的路径,要求路上的点权和最大(一个点权只能被加一次)
首先Tarjan缩点,易知一个强连通分量内任意一个点权拿到就可以拿到强连通分量内所有的点权
然后这个图就没有环了,SPFA跑最长路即可
边数500W,所以要加堆优化
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define M 500500
using namespace std;
struct edge{
int x,y;
}edges[M];
struct abcd{
int to,next;
}table[M<<1];
int head[M],tot;
int n,m,a[M],ans;
int s,k;
int dpt[M],low[M],T,stack[M],top,v[M],belong[M],cnt,cash[M];
int f[M],heap[M],pos[M];
void Push_Up(int t)
{
while(t>1&&f[heap[t]]>f[heap[t>>1]])
swap(heap[t],heap[t>>1]),swap(pos[heap[t]],pos[heap[t>>1]]),t>>=1;
}
void Insert(int x)
{
heap[++top]=x;
pos[x]=top;
Push_Up(top);
}
void Pop()
{
pos[heap[1]]=0;
heap[1]=heap[top--];
if(top) pos[heap[1]]=1;
int t=2;
while(t<=top)
{
if(t<top&&f[heap[t+1]]>f[heap[t]])
++t;
if(f[heap[t]]>f[heap[t>>1]])
swap(heap[t],heap[t>>1]),swap(pos[heap[t]],pos[heap[t>>1]]),t<<=1;
else
break;
}
}
void SPFA()
{
int i;
memset(f,0xef,sizeof f);
f[belong[s]]=cash[belong[s]];
Insert(belong[s]);
while(top)
{
int x=heap[1];Pop();
for(i=head[x];i;i=table[i].next)
if(f[table[i].to]<f[x]+cash[table[i].to])
{
f[table[i].to]=f[x]+cash[table[i].to];
if(!pos[table[i].to])
Insert(table[i].to);
else
Push_Up(pos[table[i].to]);
}
}
}
void Add(int x,int y)
{
table[++tot].to=y;
table[tot].next=head[x];
head[x]=tot;
}
void Tarjan(int x)
{
int i;
dpt[x]=low[x]=++T;
stack[++top]=x;
for(i=head[x];i;i=table[i].next)
{
if(v[table[i].to])
continue;
if(dpt[table[i].to])
low[x]=min(low[x],dpt[table[i].to]);
else
Tarjan(table[i].to),low[x]=min(low[x],low[table[i].to]);
}
if(dpt[x]==low[x])
{
int t;
++cnt;
do{
t=stack[top--];
v[t]=1;
belong[t]=cnt;
cash[cnt]+=a[t];
}while(t!=x);
}
}
int main()
{
int i,x,y;
cin>>n>>m;
for(i=1;i<=m;i++)
{
scanf("%d%d",&x,&y);
edges[i].x=x;
edges[i].y=y;
Add(x,y);
}
for(i=1;i<=n;i++)
scanf("%d",&a[i]);
cin>>s>>k;
Tarjan(s);
memset(head,0,sizeof head);tot=0;
for(i=1;i<=m;i++)
if(belong[edges[i].x]!=belong[edges[i].y])
Add(belong[edges[i].x],belong[edges[i].y]);
SPFA();
for(i=1;i<=k;i++)
{
scanf("%d",&x);
ans=max(ans,f[belong[x]]);
}
cout<<ans<<endl;
}