Tarjan + bfs HYSBZ 1179Atm
1179: [Apio2009]Atm
Time Limit: 15 Sec Memory Limit: 162 MB
Submit: 3250 Solved: 1346
[Submit][Status][Discuss]
Description
Input
第一行包含两个整数N、M。N表示路口的个数,M表示道路条数。接下来M行,每行两个整数,这两个整数都在1到N之间,第i+1行的两个整数表示第i条道路的起点和终点的路口编号。接下来N行,每行一个整数,按顺序表示每个路口处的ATM机中的钱数。接下来一行包含两个整数S、P,S表示市中心的编号,也就是出发的路口。P表示酒吧数目。接下来的一行中有P个整数,表示P个有酒吧的路口的编号
Output
输出一个整数,表示Banditji从市中心开始到某个酒吧结束所能抢劫的最多的现金总数。
Sample Input
1 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
HINT
50%的输入保证N, M<=3000。所有的输入保证N, M<=500000。每个ATM机中可取的钱数为一个非负整数且不超过4000。输入数据保证你可以从市中心沿着Siruseri的单向的道路到达其中的至少一个酒吧。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
|
# include <cstdio> # include <cstring> # include <iostream> # include <string> # include <vector> # include <queue> # include <stack> # include < set > # include <algorithm> using namespace std; #define N 500001 stack< int >Sta; queue< int >Que; vector< int >Gra[N],newGra[N]; bool isBar[N],inStack[N]; int low[N],dfn[N],belong[N],money[N],newMoney[N],cnt,Time,start; int maxMoney[N]; void Tarjan( int s) { dfn[s] = low[s] = ++Time; Sta.push(s); inStack[s] = true ; for ( int i= 0 ;i<Gra[s].size();i++) { int j = Gra[s][i]; if (dfn[j] == 0 ){ Tarjan(j); low[s] = min(low[s], low[j]); } else if (inStack[j] == true ){ low[s] = min(low[s], dfn[j]); } } if (dfn[s] == low[s]) { cnt ++; while (!Sta.empty()){ int temp = Sta.top(); Sta.pop(); belong[temp] = cnt; newMoney[cnt] += money[temp]; inStack[temp] = false ; if (temp == s) break ; } } } int spfa() { int ans = 0 ; Que.push(start); memset(maxMoney, 0 ,sizeof(maxMoney)); maxMoney[start] = newMoney[start]; while (!Que.empty()) { int now = Que.front(); Que.pop(); for ( int i = 0 ; i < newGra[now].size(); i++) { int j = newGra[now][i]; if (maxMoney[now] + newMoney[j] > maxMoney[j]) { maxMoney[j] = maxMoney[now] + newMoney[j]; Que.push(j); } if (isBar[j]) ans = max(ans, maxMoney[j]); } } return ans; } int main() { int n,m,a,b,s,p; scanf( "%d%d" ,&n,&m); for ( int i = 0 ; i < m; i++) { /* code */ scanf( "%d%d" ,&a, &b); Gra[a].push_back(b); } for ( int i = 1 ; i <= n; i++) { /* code */ scanf( "%d" ,&money[i]); } scanf( "%d%d" ,&s,&p); memset(inStack, false ,sizeof(inStack)); memset(newMoney, 0 ,sizeof(newMoney)); memset(isBar, false ,sizeof(isBar)); memset(dfn, 0 ,sizeof(dfn)); cnt = Time = 0 ; for ( int i = 1 ; i <= n; i++) if (dfn[i] == 0 ) Tarjan(i); if (cnt == 1 ) {printf( "%d" ,newMoney[cnt]); return 0 ;} for ( int i= 0 ;i<p;i++) { scanf( "%d" , &a); isBar[belong[a]] = true ; } start = belong[s]; for ( int i = 1 ; i <= n; i ++) { for ( int j = 0 ; j < Gra[i].size(); j++){ int k = Gra[i][j]; if (belong[i] != belong[k]){ newGra[belong[i]].push_back(belong[k]); } } } int ans = spfa(); printf( "%d" , ans); } |

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
|
# include <cstdio> # include <cstring> # include <iostream> # include <string> # include <vector> # include <queue> # include <stack> # include < set > # include <algorithm> using namespace std; #define N 500001 stack< int >Sta; queue< int >Que; struct edge { int u,v,next; }edge1[N],edge2[N]; bool isBar[N],inStack[N]; int low[N],dfn[N],belong[N],money[N],newMoney[N],cnt,Time,start; int maxMoney[N],head[N],head2[N]; void add( int u, int v, int id) { edge1[id].u = u; edge1[id].v = v; edge1[id].next = head[u]; head[u] = id; } void add2( int u, int v, int id) { edge2[id].u = u; edge2[id].v = v; edge2[id].next = head2[u]; head2[u] = id; } void Tarjan( int s) { dfn[s] = low[s] = ++Time; Sta.push(s); inStack[s] = true ; for ( int u = head[s]; ~u; u = edge1[u].next) { int v = edge1[u].v; if (dfn[v] == 0 ){ Tarjan(v); low[s] = min(low[s], low[v]); } else if (inStack[v] == true ){ low[s] = min(low[s], dfn[v]); } } if (dfn[s] == low[s]) { cnt ++; while (!Sta.empty()){ int temp = Sta.top(); Sta.pop(); belong[temp] = cnt; newMoney[cnt] += money[temp]; inStack[temp] = false ; if (temp == s) break ; } } } int spfa() { int ans = 0 ; Que.push(start); memset(maxMoney, 0 ,sizeof(maxMoney)); maxMoney[start] = newMoney[start]; while (!Que.empty()) { int now = Que.front(); Que.pop(); for ( int u = head2[now]; ~u; u = edge2[u].next) { int v = edge2[u].v; if (maxMoney[now] + newMoney[v] > maxMoney[v]) { maxMoney[v] = maxMoney[now] + newMoney[v]; Que.push(v); } if (isBar[v]) ans = max(ans, maxMoney[v]); } } return ans; } int main() { int n,m,a,b,s,p; scanf( "%d%d" ,&n,&m); memset(head,- 1 ,sizeof(head)); for ( int i = 0 ; i < m; i++) { /* code */ scanf( "%d%d" ,&a, &b); add(a,b,i+ 1 ); } for ( int i = 1 ; i <= n; i++) { /* code */ scanf( "%d" ,&money[i]); } scanf( "%d%d" ,&s,&p); memset(inStack, false ,sizeof(inStack)); memset(newMoney, 0 ,sizeof(newMoney)); memset(isBar, false ,sizeof(isBar)); memset(dfn, 0 ,sizeof(dfn)); cnt = Time = 0 ; for ( int i = 1 ; i <= n; i++) if (dfn[i] == 0 ) Tarjan(i); if (cnt == 1 ) {printf( "%d" ,newMoney[cnt]); return 0 ;} for ( int i= 0 ;i<p;i++) { scanf( "%d" , &a); isBar[belong[a]] = true ; } start = belong[s]; memset(head2,- 1 ,sizeof(head2)); int kkk = 0 ; for ( int i = 1 ; i <= n; i ++) { for ( int u = head[i]; ~u; u = edge1[u].next){ int v = edge1[u].v; if (belong[i] != belong[v]){ add2(belong[i],belong[v],++kkk); } } } int ans = spfa(); printf( "%d" , ans); } |
Tarjan + bfs HYSBZ 1179Atm的更多相关文章
- 4612 warm up tarjan+bfs求树的直径(重边的强连通通分量)忘了写了,今天总结想起来了。
问加一条边,最少可以剩下几个桥. 先双连通分量缩点,形成一颗树,然后求树的直径,就是减少的桥. 本题要处理重边的情况. 如果本来就两条重边,不能算是桥. 还会爆栈,只能C++交,手动加栈了 别人都是用 ...
- NOIP 2015提高组复赛
神奇的幻方 题目描述 幻方是一种很神奇的N*N矩阵:它由数字1,2,3,……,N*N构成,且每行.每列及两条对角线上的数字之和都相同. 当N为奇数时,我们可以通过以下方法构建一个幻方: 首先将1写在第 ...
- hdu-4612(无向图缩点+树的直径)
题意:给你n个点和m条边的无向图,问你如果多加一条边的话,那么这个图最少的桥是什么 解题思路:无向图缩点和树的直径,用并查集缩点: #include<iostream> #include& ...
- Codeforces Round #467(Div2)题解
凌晨起来打CF,0:05,也是我第一次codeforces 第一题: 我刚开始怀疑自己读错题了,怎么会辣么水. 判除了0的数字种类 #include <cstdio> ; ]; int m ...
- 【题解】洛谷P3119 Grass Cownoisseur G
题面:洛谷P3119 Grass Cownoisseur G 本人最近在熟悉Tarjan的题,刷了几道蓝题后,我飘了 趾高气扬地点开这道紫题,我一瞅: 哎呦!这不是分层图吗? 突然就更飘了~~~ 用时 ...
- 【BZOJ-2725】故乡的梦 Dijsktra + Tarjan + Dinic + BFS + 堆
2725: [Violet 6]故乡的梦 Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 502 Solved: 173[Submit][Status ...
- HDU4612+Tarjan缩点+BFS求树的直径
tarjan+缩点+树的直径题意:给出n个点和m条边的图,存在重边,问加一条边以后,剩下的桥的数量最少为多少.先tarjan缩点,再在这棵树上求直径.加的边即是连接这条直径的两端. /* tarjan ...
- BZOJ 1194: [HNOI2006]潘多拉的盒子( BFS + tarjan + dp )
O(S²)枚举2个诅咒机, 然后O(n²)BFS去判断. 构成一个有向图, tarjan缩点, 然后就是求DAG的最长路.. ------------------------------------- ...
- 【BFS】【并查集】【Tarjan】【LCA】Gym - 101173H - Hangar Hurdles
给你一张地图,给你q次询问,每次问你从A点到B点,最大能移动多大的箱子. 把每个点所能容纳的最大箱子求出来(BFS,八连通,一开始将所有边界点和障碍点入队).然后从大到小排序.然后用并查集将相邻(四联 ...
随机推荐
- .NET垃圾回收机制 GC
线程栈 stuck:存值类型,和引用类型的引用 先进后出,链表形式,连续摆放 CLR(公共语言运行库(Common Language Runtime))启动进程,main函数为一个线程入口 进程堆h ...
- 用jQuery实现切换动态图片
1.实现动态图片的切换只需要改变目标图片的路径
- OSS上传文件到阿里云
最近做项目,需要上传文件,因为上传到项目路径下,感觉有时候也挺不方便的,就试了一下上传文件到阿里云oss上去了, oss的使用网上有很多介绍,都是去配置一下需要的数据,然后直接调用他的api就可以了. ...
- Spring中关于AOP的实践之概念
一.什么是AOP AOP:也称作面向切面编程 在分享几个概念执行我想先举个栗子(可能例子举得并不是特别恰当): 1.假如路人A走在大街上,被一群坏人绑架了: 2.警察叔叔接到报警迅速展开行动:收集情报 ...
- c#调用word文件
大家好!我叫蓝颜,我是一名大专生.这是我第一次接触博客园,以后也会一直在. 在学校期间,参加技能大赛(物联网),接触到的C#.之后学校教务处要一个调课软件, 于是我就小试牛刀试了试.当然了,这也是我第 ...
- 原生JS替代jQuery的各种方法汇总
前端发展很快,现代浏览器原生 API 已经足够好用.我们并不需要为了操作 DOM.Event 等再学习一下 jQuery 的 API.同时由于 React.Angular.Vue 等框架的流行,直接操 ...
- Linux安装配置Mariadb
一.安装数据库Mariadb 参考:http://blog.51cto.com/12173069/2047746 从最新版本的linux系统开始,默认的是 Mariadb而不是mysql! 使用系统自 ...
- datatable的部分问题处理(动态定义列头,给某行添加事件,初始显示空数据)
一.动态定义列头 在ajax中,用datatable再去重新配置列头,当然传回的数据中,要有对应放列头的键值对 我自定义了Mock数据,用于前端自己交互. 其中,rowdata用于存放传回的数据,co ...
- 路由刷rom手册
最近对家里面那5,6个路由器下手了. 路由列表:小米mini 2台. 优酷路由宝l1,tp wdr3320,tp wr840n, 友华wr1200js,小米路由r1n 步骤: 1. 想办法开启ssh ...
- C#断点调试时属性get块逻辑执行多次
上面的例中,当打断点调试时,断点断住时, Attr1属性的get块就会执行一次. 两个断点加在逻辑中对Attr1的访问,最后发现CTest get Attr1.打印了3次. 得到的结论是:多余的2次打 ...