国家一级爬山运动员h10今天获得了一张有着密密麻麻标记的地图,在好奇心的驱使下,他又踏上了去爬山的路。
对于爬山,h10有一个原则,那就是不走回头路,于是他把地图上的所有边都标记成了有向边。他决定从点S出发,每到达一个新的节点他就可以获得一定的成就值。同时h10又是一个很珍惜时间的运动员,他不希望这次爬山的成就值白白浪费,所以最后他一定要在一个存档点停下,保存自己的成就值。
请你计算出在此次爬山运动中h10能够得到的最大成就值。保证h10能走到存档点。
n,m<=500000
时间限制 1s
空间限制 256M
用Tarjan缩环,然后跑一遍最短路就可以了,递归版Tarjan一定会爆栈,所以要用人工栈。
#include
#include
#include
#define maxn 500006
#define fr(i,a,b) for(i=a;i<=b;i++)
using namespace std;
typedef long long ll;
const ll ding=1000002;
struct poi
{
int x;
ll y;
poi *nex;
} *a[maxn+maxn],*b[maxn+maxn],*r[maxn+maxn];
int i,n,m,x,y,S,pp,col,tot,top,topp,c[maxn],f[maxn+maxn],d[maxn+maxn];
int dfn[maxn],low[maxn],sta[maxn];
ll ans,dis[maxn+maxn],v[maxn+maxn],vv[maxn+maxn];
bool kan[maxn+maxn];
void link(int x,int y)
{
poi *p=new poi;
p->x=y;
p->y=0;
p->nex=a[x];
a[x]=p;
return;
}
void linkk(int x,int y,ll z)
{
poi *p=new poi;
p->x=y;
p->y=z;
p->nex=b[x];
b[x]=p;
return;
}
void Tarjan(int x)
{
poi *p=new poi;
d[++topp]=x;
bool cai;
while (topp)
{
int u=d[topp];
if (!dfn[u])
{
dfn[u]=low[u]=++tot;
kan[u]=1;
r[u]=a[u];
sta[++top]=u;
}
cai=0;
for(p=r[u];p;p=p->nex)
if (!dfn[p->x])
{
d[++topp]=p->x;
r[u]=p->nex;
cai=1;
break;
} else if (!c[p->x])
low[u]=min(low[u],dfn[p->x]);
if (cai) continue;
if (dfn[u]==low[u])
{
++col;
while (sta[top]!=u)
{
c[sta[top]]=col;
kan[sta[top]]=0;
top--;
}
c[sta[top]]=col;
kan[sta[top]]=0;
top--;
}
low[d[--topp]]=min(low[d[topp]],low[u]);
}
return;
}
void Spfa(int x)
{
memset(dis,255,sizeof(dis));
int i=0,j=1,u;
f[1]=x,kan[x]=1,dis[x]=0;
poi *p=new poi;
while (i!=j)
{
i=i%ding+1;
u=f[i];
for(p=b[u];p;p=p->nex)
if (dis[p->x]y)
{
dis[p->x]=dis[u]+p->y;
if (!kan[p->x])
{
j=j%ding+1;
f[j]=p->x;
if (dis[f[j]]>dis[f[i+1]])
swap(f[i+1],f[j]);
kan[p->x]=1;
}
}
kan[u]=0;
}
return;
}
int main()
{
scanf("%d%d",&n,&m);
fr(i,1,m)
{
scanf("%d%d",&x,&y);
link(x,y);
}
fr(i,1,n) scanf("%d",&vv[i]);
fr(i,1,n) if (!dfn[i]) tot=top=topp=0,Tarjan(i);
poi *p=new poi;
fr(i,1,n)
{
v[c[i]]+=vv[i];
for(p=a[i];p;p=p->nex)
if (c[p->x]!=c[i])
linkk(c[i]+col,c[p->x],0);
}
fr(i,1,col) linkk(i,i+col,v[i]);
scanf("%d%d",&S,&pp);
Spfa(c[S]);
fr(i,1,pp)
{
scanf("%d",&x);
ans=max(ans,dis[c[x]+col]);
}
printf("%lld\n",ans);
return 0;
}