题意:中文题面
解题思路:因为他能重复走且边权都正的,那么肯定一个环的是必须走完的,所以先缩点,在重新建一个图跑最长路
代码:
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
using namespace std;
const int inf=0x7f7f7f7f;
const int maxn=500500;
struct node
{
int num;
int dist;
node(int _num,int _dist):num(_num),dist(_dist){}
friend bool operator<(node a,node b)
{
return a.dist<b.dist;
}
};
struct Edge
{
int next;
int to;
int w;
}edge[maxn],EDGE[maxn];
int low[maxn];
int dfn[maxn];
int scc_cnt;
int cnt,indexx,step,CNT;
int instack[maxn];
int sccno[maxn];
int visit[maxn];
int head[maxn],HEAD[maxn];
int w[maxn];
int val[maxn];
int dist[maxn];
int flag[maxn];
int x[maxn],y[maxn];
int tx,ty;
int n,m;
int cot,start;
int ans;
vector<int>scc[maxn];
void add(int u,int v)
{
edge[cnt].next=head[u];
edge[cnt].to=v;head[u]=cnt++;
}
void add2(int u,int v,int w)
{
EDGE[CNT].next=HEAD[u];EDGE[CNT].to=v;
EDGE[CNT].w=w;HEAD[u]=CNT++;
}
void tarjan(int u)
{
low[u]=dfn[u]=++step;
instack[++indexx]=u;
visit[u]=1;
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].to;
if(!dfn[v])
{
tarjan(v);
low[u]=min(low[u],low[v]);
}
else if(visit[v])
{
low[u]=min(low[u],dfn[v]);
}
}
if(dfn[u]==low[u])
{
scc_cnt++;
scc[scc_cnt].clear();
do
{
scc[scc_cnt].push_back(instack[indexx]);
sccno[instack[indexx]]=scc_cnt;
visit[instack[indexx]]=0;
indexx--;
}
while(u!=instack[indexx+1]);
}
return;
}
void dij(int u)
{
fill(dist+1,dist+1+scc_cnt,-1);
dist[u]=0;
priority_queue<node>que;
que.push(node(u,dist[u]));
while(!que.empty())
{
node z=que.top();que.pop();
int now=z.num;
for(int i=HEAD[now];i!=-1;i=EDGE[i].next)
{
int v=EDGE[i].to;
if(dist[v]<dist[now]+EDGE[i].w)
{
dist[v]=dist[now]+EDGE[i].w;//cout<<dist[v]<<endl;
que.push(node(v,dist[v]));
} }
}
}
void init()
{
memset(head,-1,sizeof(head));cnt=scc_cnt=indexx=step=0;
memset(low,0,sizeof(low));memset(dfn,0,sizeof(dfn));
memset(visit,0,sizeof(visit));memset(HEAD,-1,sizeof(HEAD));CNT=0;
}
int main()
{
int n,m;
init();
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
scanf("%d%d",&tx,&ty);
x[i]=tx;y[i]=ty;
add(tx,ty);
}
for(int i=1;i<=n;i++)
if(!dfn[i])
tarjan(i);
for(int i=1;i<=n;i++)
scanf("%d",&val[i]);
scanf("%d%d",&start,&cot);
for(int i=1;i<=cot;i++)
scanf("%d",&flag[i]);
for(int i=1;i<=scc_cnt;i++)
{
for(int j=0;j<scc[i].size();j++)
{
w[i]+=val[scc[i][j]];
if(scc[i][j]==start)
start=i;
}
}
add2(0,start,w[start]);
for(int i=1;i<=m;i++)
{
if(sccno[x[i]]==sccno[y[i]])
continue;
else
{
add2(sccno[x[i]],sccno[y[i]],w[sccno[y[i]]]);
}
}
dij(0);
ans=0;
for(int i=1;i<=cot;i++)
{
ans=max(ans,dist[sccno[flag[i]]]);
}
printf("%d\n",ans);
}