【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; }
相关文章推荐
- 第9章:面向对象变量与关键字
- Mac 下gdb 的安装过程
- opencv实现多图像读取并显示,sprintf_s函数,static_cast
- stream_context_create() 模拟 POST、GET数据
- HDU 5873 - Football Match【2016大连区域赛网络赛1006】
- Hive在spark2.0.0启动时无法访问../lib/spark-assembly-*.jar: 没有那个文件或目录的解决办法
- javascript网页特效——table
- java util :获取国家省份城市工具类
- 关闭不断重启的进程
- MySQL 数据库增量数据恢复案例
- graphx之图迭代
- matlab .p文件
- JavaScript 中对变量和函数声明的“提前(hoist)”
- 找出前50个素数,构成素数表
- 51nod 1137 矩阵乘法
- Linux下设置静态IP和获取动态IP的方法
- 第二次CCF-3-命令行选项(字符串处理)
- python将图片转换为字符画
- Swivel
- Broadcast