传送门
题目大意:给定n个点,m条边的有向图,每个点有权值,给点起点和若干终点,求从起点到某一终点的路径,使得路径权值最大,边可重复走
思路:缩点
由于可重复走的缘故,对于环我们缩点
问题转化为一棵树,求权值最大的路径
如果是权值最小,显然用迪杰斯特拉求最短路,类似的,我们可以求最长路。
不过用迪杰斯特拉不行,取负也不行,因为用迪杰斯特拉的前提就是不能有负权边,我们可以用spfa(树,不存在负权环)
//tarjan缩点
#include <iostream>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <vector>
#include <queue>
using namespace std;
#define IOS ios::sync_with_stdio(false)
#define _for(i,a,b) for(int i=(a) ;i<=(b) ;i++)
#define _rep(i,a,b) for(int i=(a) ;i>=(b) ;i--)
#define mst(v,s) memset(v,s,sizeof(v))
#define pb push_back
#define int long long
#define inf 0x3f3f3f3f
typedef long long ll;
const int N=5e5+10;
vector<int > G[N];
int n,m,s,p;
int x[N],y[N],a[N],b[N],f[N],dfn[N],low[N];//dfn第一次访问 low时间戳
int sta[N],pd[N],top;//栈 是否在栈中 栈顶指针
int col[N];//缩点后每个点所在的强联通块
int ti,tot,ans;//时间 总的强联通块数量 答案
int sum[N],dis[N];
void tarjan(int x)
{
sta[++top]=x;//入栈
dfn[x]=low[x]=++ti;//按照访问时间给dfn和时间戳赋值
pd[x]=1;//入栈
for(int i=0 ;i<G[x].size() ;i++)
{
int y = G[x][i];
if( dfn[y] == 0 )
{
tarjan(y);
low[x] =min(low[x],low[y]);
}
else if( pd[y] ) low[x] =min(low[x] ,low[y]);
}
if( dfn[x] == low[x])//时间戳不变,说明无法更新了,强联通块到此可以打包
{
tot++;
while( sta[top+1] != x)//如果x还没退栈
{
col[sta[top]]=tot;//在x上方的元素打包在一起
sum[tot] += a[sta[top]];//计算连通块的权值和
pd[sta[top--]]=0;//退栈(更新pd 和 stack)
}
}
}
queue < int > q;
int v[N];
void spfa(int st)//求最长路
{
q.push(col[st]);
v[col[st]]=1;
dis[col[st]]=sum[col[st]];
while( !q.empty() )
{
int x=q.front();
q.pop();
v[x]=0;//退队
for(int i=0 ;i<G[x].size() ;i++)
{
int y = G[x][i];
int len = sum[y];
if( dis[x] + len > dis[y] )
{
dis[y] = dis[x] + len;
q.push(y);
//更新了边就要将x放入队列
if( !v[y] )
{
v[y]=1;
q.push(y);//放置队尾去更新
}
}
}
}
}
void solve()
{
_for(i,1,n)
{
if( !dfn[i]) tarjan(i);
}
//缩点后重新建图
mst(G,0);
//建图
_for(i,1,m)
{
if( col[x[i]]!=col[y[i]]) //不在一个强联通块里
{
G[col[x[i]]].pb(col[y[i]]);
}
}
spfa(s);
ans = sum[col[s]];//避免起点自成一个强联通块
_for(i,1,p)
{
ans = max(ans, dis[col[b[i]]]);
}
cout<<ans<<endl;
}
signed main()
{
IOS;
///!!!
// freopen("data.txt","r",stdin);
///!!!
cin>>n>>m;
_for(i,1,m)
{
cin>>x[i]>>y[i];
G[x[i]].pb(y[i]);
}
_for(i,1,n) cin>>a[i];
cin>>s>>p;
_for(i,1,p) cin>>b[i];
solve();
}