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 -- the king does not want to accidentally enter your area.
In order to satisfy this condition, you have to destroy some roads.
What‘s worse, you have to pay for that -- each road is associated with
some positive cost. That is, your final income is the total value of the
cities you take, minus the total cost of destroyed roads.

Note
that each road is a unidirectional, i.e only one direction is available.
Some cities are reserved for the king, so you cannot take any of them
even if they‘re unreachable from the capital. The capital city is always
the city number 1.

Input

The
first line contains a single integer T (T <= 20), the number of test
cases. Each case begins with three integers n, m, f (1 <= f < n
<= 1000, 1 <= m < 100000), the number of cities, number of
roads, and number of cities that you can take. Cities are numbered 1 to
n. Each of the following m lines contains three integers u, v, w,
denoting a road from city u to city v, with cost w. Each of the
following f lines contains two integers u and w, denoting an available
city u, with value w.

Output

For
each test case, print the case number and the best final income in the
first line. In the second line, print e, the number of roads you should
destroy, followed by e integers, the IDs of the destroyed roads. Roads
are numbered 1 to m in the same order they appear in the input. If there
are more than one solution, any one will do.

Sample Input

2

4 4 2

1 2 2

1 3 3

3 2 4

2 4 1

2 3

4 4

4 4 2

1 2 2

1 3 3

3 2 1

2 4 1

2 3

4 4

Sample Output

Case 1:

3
1 4

Case 2:

4
2 1 3

题意:n个城市,m条有向带权边。可以选择f个城市,1是首都,要切断1和选择城市的路线,总价值是选择城市的价值减去摧毁的道路,求最大价值。

将带权的点连接到t上,容量就是该点的权值,s连接1,容量是INF。求最小割,利用总的点权和减去最小割就是获得的收益。

  1 #include <iostream>
  2 #include <string.h>
  3 #include <stdio.h>
  4 #include <vector>
  5 #include <queue>
  6 #define INF 0x3f3f3f3f
  7 using namespace std;
  8 const int M = 210010;
  9 struct Nod {
 10     int to, cap, next, index;
 11 }edge[M];
 12 int T, n, m, f, s, t;
 13 int head[M], level[M], vis[M], iter[M], sum, num;
 14 void init() {
 15     memset(head, -1, sizeof(head));
 16     memset(vis, 0, sizeof(vis));
 17     num = 0;
 18     sum = 0;
 19 }
 20 void add_edge(int u, int v, int cap, int index) {
 21     edge[num].to = v; edge[num].cap = cap; edge[num].next = head[u]; edge[num].index = index; head[u] = num++;
 22     edge[num].to = u; edge[num].cap = 0; edge[num].next = head[v]; edge[num].index = -1; head[v] = num++;
 23 }
 24 bool bfs(int s, int t) {
 25     memset(level, -1, sizeof(level));
 26     level[s] = 0;
 27     queue<int> que;
 28     que.push(s);
 29     while(!que.empty()) {
 30         int v = que.front();
 31         que.pop();
 32         for(int i = head[v]; i != -1; i = edge[i].next) {
 33             int u = edge[i].to;
 34             if(level[u] < 0 && edge[i].cap) {
 35                 level[u] = level[v] + 1;
 36                 que.push(u);
 37             }
 38         }
 39     }
 40     return level[t] != -1;
 41 }
 42 int dfs(int v, int t, int f) {
 43     if(v == t) return f;
 44     for(int &i = iter[v]; i != -1; i = edge[i].next) {
 45         int u = edge[i].to;
 46         if(level[u] > level[v] && edge[i].cap > 0) {
 47             int d = dfs(u, t, min(f, edge[i].cap));
 48             if(d > 0) {
 49                 edge[i].cap -= d;
 50                 edge[i^1].cap += d;
 51                 return d;
 52             }
 53         }
 54     }
 55     level[v] = -1;
 56     return 0;
 57 }
 58 int max_flow(int s, int t) {
 59     int flow = 0;
 60     while(bfs(s, t)) {
 61         for(int i = 0; i <= t + 10; i ++) iter[i] = head[i];
 62         int f = 0;
 63         while((f = dfs(s, t, INF)) > 0) flow += f;
 64     }
 65     return flow;
 66 }
 67 void dfs(int u, int fa) {
 68     for(int i = head[u]; i != -1; i = edge[i].next) {
 69         int v = edge[i].to;
 70         if(!vis[v] && edge[i].cap) {
 71             vis[v] = true;
 72             dfs(v, u);
 73         }
 74     }
 75 }
 76 int main() {
 77     ios::sync_with_stdio(false);
 78     // cin >> T;
 79     scanf("%d", &T);
 80     int cas = 1;
 81     while(T--) {
 82         // cin >> n >> m >> f;
 83         scanf("%d %d %d", &n, &m, &f);
 84         init();
 85         add_edge(s, 1, INF, -1);
 86         s = 0, t = n + 1;
 87         for(int i = 1; i <= m; i ++) {
 88             int u, v, w;
 89             scanf("%d %d %d", &u, &v, &w);
 90             add_edge(u, v, w, i);
 91         }
 92         for(int i = 1; i <= f; i ++) {
 93             int u, w;
 94             scanf("%d %d", &u, &w);
 95             add_edge(u, t, w, -1);
 96             sum += w;
 97         }
 98         int ans = max_flow(s, t);
 99         ans = sum - ans;
100         printf("Case %d: %d\n",cas++, ans);
101         vis[1] = true;
102         dfs(1, -1);
103         queue<int> que;
104         for(int i = 0; i < num; i += 2) {//0正1负
105             if(vis[edge[i^1].to] && !vis[edge[i].to] && edge[i].index != -1) que.push(edge[i].index);
106         }
107         printf("%d",(int)que.size());
108         while(!que.empty()) {
109             printf(" %d",que.front());
110             que.pop();
111         }
112         printf("\n");
113     }
114     return 0;
115 }
时间: 2024-11-06 11:26:42

HDU 3251 Being a Hero 最小割的相关文章

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 3251 Being a Hero(最小割)经典

Being a Hero Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1229    Accepted Submission(s): 387 Special Judge Problem Description You are the hero who saved your country. As promised, the ki

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