第一行包含两个整数N、M。N表示路口的个数,M表示道路条数。接下来M行,每行两个整数,这两个整数都在1到N之间,第i+1行的两个整数表示第i条道路的起点和终点的路口编号。接下来N行,每行一个整数,按顺序表示每个路口处的ATM机中的钱数。接下来一行包含两个整数S、P,S表示市中心的编号,也就是出发的路口。P表示酒吧数目。接下来的一行中有P个整数,表示P个有酒吧的路口的编号
输出一个整数,表示Banditji从市中心开始到某个酒吧结束所能抢劫的最多的现金总数。
50%的输入保证N, M<=3000。所有的输入保证N, M<=500000。每个ATM机中可取的钱数为一个非负整数且不超过4000。输入数据保证你可以从市中心沿着Siruseri的单向的道路到达其中的至少一个酒吧。
解题思路:先强连通,再用spfa(可把边权改为负数再求最短路)
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
using namespace std;
const int maxn=500001;
int len,len1,S,tcc,head,size,n,m,tail;
int to[500001],to1[500001],next[500001],next1[500001];
int h[500001],h1[500001],dfn[500001],twf[500001],dui[500001],zhi[500001];
int q[500001],pan[500001],v[500001],dis[500001];
bool b[500001];
inline int read()
{
char y; int x=0,f=1; y=getchar();
while (y<'0' || y>'9') {if (y=='-') f=-1; y=getchar();}
while (y>='0' && y<='9') {x=x*10+int(y)-48; y=getchar();}
return x*f;
}
void insert(int x,int y)
{
++len; to[len]=y; next[len]=h[x]; h[x]=len;
}
void insert1(int x,int y)
{
++len1; to1[len1]=y; next1[len1]=h1[x]; h1[x]=len1;
}
void dfs(int now)
{
++tcc; ++head; q[head]=now; dfn[now]=twf[now]=tcc; pan[now]=1;
int u=h[now];
while (u!=0)
{
if (pan[to[u]]==0)
{
dfs(to[u]);
}
if (pan[to[u]]==1)
{
twf[now]=min(twf[now],twf[to[u]]);
}
u=next[u];
}
if (dfn[now]==twf[now])
{
++size;
while (q[head]!=now)
{
--head;
dui[q[head+1]]=size; zhi[size]+=v[q[head+1]];
pan[q[head+1]]=2;
}
--head; dui[now]=size; zhi[size]+=v[now]; pan[now]=2;
}
}
int main()
{
freopen("large-tree-0.in","r",stdin);
freopen("main.out","w",stdout);
n=read(); m=read();
for (int i=1;i<=m;++i)
{
int x=read(); int y=read();
insert(x,y);
}
for (int i=1;i<=n;++i)
{
v[i]=read();
}
S=read();
size=0; head=0; tcc=0;
memset(dfn,0,sizeof(dfn));
memset(twf,0,sizeof(twf));
memset(pan,0,sizeof(pan));
for (int i=1;i<=n;++i)
if (pan[i]==0)
{
dfs(i);
}
for (int i=1;i<=n;++i)
{
int u=h[i];
while (u!=0)
{
int u1=dui[i]; int u2=dui[to[u]];
if (u1!=u2)
{
insert1(u1,u2);
}
u=next[u];
}
}
memset(dis,0x7f,sizeof(dis));
memset(b,true,sizeof(b));
tail=0; head=0; ++tail; q[tail]=dui[S]; dis[dui[S]]=-zhi[dui[S]]; b[dui[S]]=false;
while(head<tail)
{
head=(head+1)%maxn;
int u=h1[q[head]];
while (u!=0)
{
if (dis[q[head]]-zhi[to1[u]]<dis[to1[u]])
{
dis[to1[u]]=dis[q[head]]-zhi[to1[u]];
if (b[to1[u]])
{
b[to1[u]]=false;
tail=(tail+1)%maxn; q[tail]=to1[u];
}
}
u=next1[u];
}
b[q[head]]=true;
}
int q=read();
int ans=-1;
for (int i=1;i<=q;++i)
{
int x=read();
if (dui[x]==dui[S]) ans=max(ans,zhi[S]);else
ans=max(ans,-dis[dui[x]]);
}
printf("%d",ans);
}