您的位置:首页 > 其它

【JZOJ4771】爬山

2016-09-12 19:59 295 查看

Description

国家一级爬山运动员h10今天获得了一张有着密密麻麻标记的地图,在好奇心的驱使下,他又踏上了去爬山的路。

对于爬山,h10有一个原则,那就是不走回头路,于是他把地图上的所有边都标记成了有向边。他决定从点S出发,每到达一个新的节点他就可以获得一定的成就值。同时h10又是一个很珍惜时间的运动员,他不希望这次爬山的成就值白白浪费,所以最后他一定要在一个存档点停下,保存自己的成就值。

请你计算出在此次爬山运动中h10能够得到的最大成就值。保证h10能走到存档点。

Data Constraint

对于 30% 的数据, N,M≤1000,并且地图为有向无环图。

对于 100% 的数据, N,M≤500000。(数据有梯度,注意答案的大小)

Solution

30%的数据随便一个水dp就过了,因为是有向无环图。

那么100%的数据可能有环,怎么办呢?

我们发现,每个环里的点一定是可以全部取到的。

那么Tarjan缩点重连边,像30%数据那样dp就可以了。

注意,这题N很大,windows编译下递归会爆栈,那就打个人工栈吧(说的轻巧)。

Code

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define fo(i,j,k) for(int i=j;i<=k;i++)
#define fd(i,j,k) for(int i=j;i>=k;i--)
#define N 500001
#define M 1000001
#define ll long long
using namespace std;
int dfn
,low
;
int dep=0,top=0;
int st
;
int to[M],next[M],last[M],num=0;
int g[M],nx[M],ls[M],cnt=0;
int c
,tot=0;
bool bz
;
ll a
,b
;
void link1(int x,int y)
{
cnt++;
g[cnt]=y;
nx[cnt]=ls[x];
ls[x]=cnt;
}
void link(int x,int y)
{
num++;
to[num]=y;
next[num]=last[x];
last[x]=num;
}
int cur
;
bool vis
;
int fa
;
int sta
,top1=0;
void tarjan(int s)
{
st[top=1]=s;
while(top)
{
int x=st[top];
if(!dfn[x])
{
low[x]=dfn[x]=++dep;
sta[++top1]=x;
bz[x]=true;
}
int p,q;
int i;
for(i=last[x];i;i=next[i])
{
int v=to[i];
if(!dfn[v])
{
//tarjan(v);
fa[v]=x;
break;
}
else if(bz[v]) low[x]=min(low[x],dfn[v]);
}
if(!i && top>1) low[st[top-1]]=min(low[st[top-1]],low[x]);
if(!i)
{
if(low[x]==dfn[x])
{
tot++;
while(sta[top1+1]!=x && top1)
{
c[sta[top1]]=tot;
b[tot]+=a[sta[top1]];
bz[sta[top1]]=false;
top1--;
}
}
top--;
}
else st[++top]=to[i];
}
}
ll f
;
int d
;
int main()
{
int n,m;
scanf("%d %d",&n,&m);
fo(i,1,m)
{
int x,y;
scanf("%d %d",&x,&y);
link(x,y);
}
fo(i,1,n) scanf("%d",&a[i]);
int s,p;
cin>>s>>p;
tarjan(s);
fo(i,1,n)
for(int j=last[i];j;j=next[j])
{
int v=to[j];
if(c[v]!=c[i]) link1(c[i],c[v]);
}
int l=0,r=1;
d[1]=c[s];
f[c[s]]=b[c[s]];
while(l<r)
{
l++;
int x=d[l];
for(int i=ls[x];i;i=nx[i])
{
int v=g[i];
f[v]=max(f[v],f[x]+b[v]);
d[++r]=v;
}
}
ll ans=0;
fo(i,1,p)
{
int x;
scanf("%d",&x);
ans=max(ans,f[c[x]]);
}
cout<<ans;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: