HDU 3215 Being a Hero(最小割)

题意:一个英雄,分到几个城市,每个城市有一个价值,但是要求分到城市后,必须破坏掉道路使得首都1都不能到达,破坏道路有开销,问最大能获得的收益和需要破坏的道路ID

思路:最小割,城市1做源点,有向边建图,容量为代价,然后每个可以分的城市连到汇点,容量为价值,跑一下最小割即可

代码:

[cpp] view plaincopy

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <queue>
  4. #include <algorithm>
  5. using namespace std;
  6. const int MAXNODE = 1005;
  7. const int MAXEDGE = 300005;
  8. typedef int Type;
  9. const Type INF = 0x3f3f3f3f;
  10. struct Edge {
  11. int u, v, id;
  12. Type cap, flow;
  13. Edge() {}
  14. Edge(int u, int v, Type cap, Type flow, int id) {
  15. this->u = u;
  16. this->v = v;
  17. this->cap = cap;
  18. this->flow = flow;
  19. this->id = id;
  20. }
  21. };
  22. struct Dinic {
  23. int n, m, s, t;
  24. Edge edges[MAXEDGE];
  25. int first[MAXNODE];
  26. int next[MAXEDGE];
  27. bool vis[MAXNODE];
  28. Type d[MAXNODE];
  29. int cur[MAXNODE];
  30. vector<int> cut;
  31. void init(int n) {
  32. this->n = n;
  33. memset(first, -1, sizeof(first));
  34. m = 0;
  35. }
  36. void add_Edge(int u, int v, Type cap, int id) {
  37. edges[m] = Edge(u, v, cap, 0, id);
  38. next[m] = first[u];
  39. first[u] = m++;
  40. edges[m] = Edge(v, u, 0, 0, id);
  41. next[m] = first[v];
  42. first[v] = m++;
  43. }
  44. bool bfs() {
  45. memset(vis, false, sizeof(vis));
  46. queue<int> Q;
  47. Q.push(s);
  48. d[s] = 0;
  49. vis[s] = true;
  50. while (!Q.empty()) {
  51. int u = Q.front(); Q.pop();
  52. for (int i = first[u]; i != -1; i = next[i]) {
  53. Edge& e = edges[i];
  54. if (!vis[e.v] && e.cap > e.flow) {
  55. vis[e.v] = true;
  56. d[e.v] = d[u] + 1;
  57. Q.push(e.v);
  58. }
  59. }
  60. }
  61. return vis[t];
  62. }
  63. Type dfs(int u, Type a) {
  64. if (u == t || a == 0) return a;
  65. Type flow = 0, f;
  66. for (int &i = cur[u]; i != -1; i = next[i]) {
  67. Edge& e = edges[i];
  68. if (d[u] + 1 == d[e.v] && (f = dfs(e.v, min(a, e.cap - e.flow))) > 0) {
  69. e.flow += f;
  70. edges[i^1].flow -= f;
  71. flow += f;
  72. a -= f;
  73. if (a == 0) break;
  74. }
  75. }
  76. return flow;
  77. }
  78. Type Maxflow(int s, int t) {
  79. this->s = s; this->t = t;
  80. Type flow = 0;
  81. while (bfs()) {
  82. for (int i = 0; i < n; i++)
  83. cur[i] = first[i];
  84. flow += dfs(s, INF);
  85. }
  86. return flow;
  87. }
  88. void MinCut() {
  89. cut.clear();
  90. for (int i = 0; i < m; i += 2) {
  91. if (vis[edges[i].u] && !vis[edges[i].v] && edges[i].id)
  92. cut.push_back(i);
  93. }
  94. int sz = cut.size();
  95. printf("%d", sz);
  96. for (int i = 0; i < sz; i++)
  97. printf(" %d", edges[cut[i]].id);
  98. printf("\n");
  99. }
  100. } gao;
  101. int t, n, m, f;
  102. int main() {
  103. int cas = 0;
  104. scanf("%d", &t);
  105. while (t--) {
  106. scanf("%d%d%d", &n, &m, &f);
  107. gao.init(n + 1);
  108. int u, v, w, tot = 0;
  109. for (int i = 1; i <= m; i++) {
  110. scanf("%d%d%d", &u, &v, &w);
  111. gao.add_Edge(u, v, w, i);
  112. }
  113. while (f--) {
  114. scanf("%d%d", &u, &w);
  115. tot += w;
  116. gao.add_Edge(u, 0, w, 0);
  117. }
  118. printf("Case %d: %d\n", ++cas, tot - gao.Maxflow(1, 0));
  119. gao.MinCut();
  120. }
  121. return 0;
  122. }
时间: 2024-11-03 16:24:04

HDU 3215 Being a Hero(最小割)的相关文章

HDU 3251 Being a Hero 最小割

Problem Description You are the hero who saved your country. As promised, the king will give you some cities of the country, and you can choose which ones to own! But don't get too excited. The cities you take should NOT be reachable from the capital

HDU 4289 Control (网络流-最小割)

Control Problem Description You, the head of Department of Security, recently received a top-secret information that a group of terrorists is planning to transport some WMD 1 from one city (the source) to another one (the destination). You know their

HDU 6214 Smallest Minimum Cut 最小割,权值编码

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6214 题意:求边数最小的割. 解法: 建边的时候每条边权 w = w * (E + 1) + 1; 这样得到最大流 maxflow / (E + 1) ,最少割边数 maxflow % (E + 1) 道理很简单,如果原先两类割边都是最小割,那么求出的最大流相等 但边权变换后只有边数小的才是最小割了 乘(E+1)是为了保证边数叠加后依然是余数,不至于影响求最小割的结果 因为假设最小割=k,那么现在新

HDU 5889 Barricade 【BFS+最小割 网络流】(2016 ACM/ICPC Asia Regional Qingdao Online)

Barricade Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 997    Accepted Submission(s): 306 Problem Description The empire is under attack again. The general of empire is planning to defend his

HDU 4289:Control(最小割)

http://acm.hdu.edu.cn/showproblem.php?pid=4289 题意:有n个城市,m条无向边,小偷要从s点开始逃到d点,在每个城市安放监控的花费是sa[i],问最小花费可以监控到所有小偷. 思路:求最小割可以转化为最大流.每个城市之间拆点,流量是sa[i],再增加一个超级源点S和s相连,增加一个超级汇点T,让d的第二个点和T相连.然后就可以做了. 1 #include <cstdio> 2 #include <algorithm> 3 #include

HDU 3452 Bonsai(网络流之最小割)

题目地址:HDU 3452 最小割水题. 源点为根节点.再另设一汇点,汇点与叶子连边. 对叶子结点的推断是看度数是否为1. 代码例如以下: #include <iostream> #include <cstdio> #include <string> #include <cstring> #include <stdlib.h> #include <math.h> #include <ctype.h> #include &l

HDU 3526 Computer Assembling(最小割)

http://acm.hdu.edu.cn/showproblem.php?pid=3526 题意:有个屌丝要配置电脑,现在有n个配件需要购买,有两家公司出售这n个配件,还有m个条件是如果配件x和配件y在不同公司买的话,需要花费额外的w元.现在需要计算购买这n个配件的最小花费. 思路: 一开始想的费用流,但好像不太行?? 其实一看到二选一的话就首先应该往最小割和二分图这个方向去想一想的. 这题用最小割来做,对于这m条件,在这两个顶点之间加两条有向边. 1 #include<iostream>

HDU 3657 Game(取数 最小割)经典

Game Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1065    Accepted Submission(s): 449 Problem Description onmylove has invented a game on n × m grids. There is one positive integer on each g

HDU 5294(Tricks Device-最短路最小割)[Template:SPFA]

Tricks Device Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 2389    Accepted Submission(s): 635 Problem Description Innocent Wu follows Dumb Zhang into a ancient tomb. Innocent Wu's at the en