【bzoj1179】【apio2009】Atm【强连通分量缩点+spfa】
2015-09-10 19:41
351 查看
Description
Input
第一行包含两个整数N、M。N表示路口的个数,M表示道路条数。接下来M行,每行两个整数,这两个整数都在1到N之间,第i+1行的两个整数表示第i条道路的起点和终点的路口编号。接下来N行,每行一个整数,按顺序表示每个路口处的ATM机中的钱数。接下来一行包含两个整数S、P,S表示市中心的编号,也就是出发的路口。P表示酒吧数目。接下来的一行中有P个整数,表示P个有酒吧的路口的编号Output
输出一个整数,表示Banditji从市中心开始到某个酒吧结束所能抢劫的最多的现金总数。Sample Input
6 71 2
2 3
3 5
2 4
4 1
2 6
6 5
10
12
8
16
1
5
1 4
4
3
5
6
Sample Output
47HINT
50%的输入保证N, M<=3000。所有的输入保证N, M<=500000。每个ATM机中可取的钱数为一个非负整数且不超过4000。输入数据保证你可以从市中心沿着Siruseri的单向的道路到达其中的至少一个酒吧。题解:缩点跑spfa即可。
代码:
#include<iostream> #include<cstdio> #include<cstring> #define N 500010 using namespace std; int n,m,x,y,point ,next ,point2 ,next2 ,cnt,cnt2,h,t,p,ans; int s ,scc ,top,pre ,low ,ss,v ,be,dis ,l[N*10],size ; bool f ,fc ; struct use{int st,en;}; use e ,b ; void add(int x,int y) { next[++cnt]=point[x];point[x]=cnt; e[cnt].st=x;e[cnt].en=y; } void add2(int x,int y) { next2[++cnt2]=point2[x];point2[x]=cnt2; b[cnt2].st=x;b[cnt2].en=y; } void dfs(int x) { pre[x]=low[x]=++ss;s[++top]=x; for (int i=point[x];i;i=next[i]) { if (!pre[e[i].en]){dfs(e[i].en);low[x]=min(low[e[i].en],low[x]);} else if(!scc[e[i].en]) low[x]=min(low[x],pre[e[i].en]); } if (pre[x]==low[x]) { scc[0]++; while (top) { scc[s[top--]]=scc[0]; size[scc[0]]+=v[s[top+1]]; if (fc[s[top+1]]) f[scc[0]]=true; if (s[top+1]==x) break; } } } void tarjan() { memset(scc,0,sizeof(scc)); for (int i=1;i<=n;i++) if (!pre[i]) dfs(i); } void rebuild() { for (int i=1;i<=n;i++) { for (int j=point[i];j;j=next[j]) { if (scc[i]!=scc[e[j].en]) add2(scc[i],scc[e[j].en]); } } } void spfa(int x) { bool f ; memset(f,false,sizeof(f)); h=0;t=1;dis[x]=size[x];l[t]=x;f[x]=true; while (h<t) { int u=l[++h]; f[u]=false; for (int i=point2[u];i;i=next2[i]) { if (dis[b[i].en]<dis[u]+size[b[i].en]) { dis[b[i].en]=dis[u]+size[b[i].en]; if (!f[b[i].en]) { l[++t]=b[i].en; f[b[i].en]=true; } } } } } int main() { scanf("%d%d",&n,&m); for (int i=1;i<=m;i++) { scanf("%d%d",&x,&y); add(x,y); } for (int i=1;i<=n;i++) scanf("%d",&v[i]); scanf("%d%d",&be,&p); for (int i=1;i<=p;i++){scanf("%d",&x);fc[x]=true;} tarjan(); //for (int i=1;i<=scc[0];i++) cout<<size[i]<<endl; rebuild(); spfa(scc[be]); for (int i=1;i<=scc[0];i++) if (f[i]) ans=max(ans,dis[i]); cout<<ans<<endl; }
相关文章推荐
- BZOJ 2120 色彩数 暴力
- 浅谈数据结构-平衡二叉树
- GitHub--Windows下command line创建与提交
- 如何搭建一个Linux驱动编写环境(centos)
- Spark on Yarn+Hbase环境搭建指南(四)NTP服务设置
- Maven多工程依赖在Eclipse中发布到Server被依赖工程没有生成jar的问题
- 《剑指offer》矩形覆盖
- Android 学习第8课,android的布局方式
- Android 学习第9课,java android 项目的安装与启动过程
- ZOJ 3466 The Hive II (插头DP,变形)
- 在dialog程序中如何call screen屏幕位置
- UVA 753(最大流匹配)
- 【hihoCoder】Tower Defense Game
- 优秀程序设计的18大原则
- HDU_1175_连连看
- [leetcode]Word Frequency
- poj 2049 Finding Nemo 建图技巧型最短路
- netty5源码分析(1)--学习笔记
- 捉虫记2:windows程序句柄泄露的上下文环境
- block回调