hdoj 3251 Being a Hero 【建图后求解最小割 + 输出任意一组最小割里面边 的编号】
来源:互联网 发布:山东省青岛市 阿里云 编辑:程序博客网 时间:2024/06/04 18:34
Being a Hero
Time Limit: 20000/10000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1252 Accepted Submission(s): 395
Special Judge
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.
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
24 4 21 2 21 3 33 2 42 4 12 34 44 4 21 2 21 3 33 2 12 4 12 34 4
Sample Output
Case 1: 31 4Case 2: 42 1 3
犯二了,坐两个多小时的车。累死啦。/(ㄒoㄒ)/~~
题意:有N个城市(编号从1到N)和连接城市的M条有向边。你可以选择F个城市,但要求城市1不能到达这F个城市,因此你需要破坏一些边。现在给你破坏每条边的花费以及F个城市的价值,问你能得到的最大价值,并输出需要破坏的边数以及该边的编号(若有多种方案,可以输出任意一种)。
思路:求最小割,最大价值就是F个城市的总价值-最小割。至于输出最小割里面边的编号,只需在残量网络里找到城市1能到达的所有点,这些点必定构成一个集合S。最后遍历M条有向边的正向弧,若弧的起点在S集并且终点不在,那么该弧就是最小割里面的一条边。
建图:设置超级源点source,超级汇点sink
1,有向边<u, v>建边,边权为破坏该边的花费;
2,source向城市1建边,容量为无穷大;
3,选择的F个城市向sink建边,容量为该城市的价值。
source->sink跑一次最大流 即求出最小割。
AC代码:
#include <cstdio>#include <cstring>#include <algorithm>#include <queue>#define MAXN 1010#define MAXM 300000+10#define INF 0x3f3f3f3fusing namespace std;struct Edge{ int from, to, cap, flow, ID, next;//ID记录边的编号};Edge edge[MAXM];int head[MAXN], edgenum;int dist[MAXN], cur[MAXN];bool vis[MAXN];int N, M, F;int source, sink;void init(){ edgenum = 0; memset(head, -1, sizeof(head));}void addEdge(int u, int v, int w, int id){ Edge E1 = {u, v, w, 0, id, head[u]}; edge[edgenum] = E1; head[u] = edgenum++; Edge E2 = {v, u, 0, 0, id, head[v]}; edge[edgenum] = E2; head[v] = edgenum++;}int val;//所有能获取城市的价值void getMap(){ source = 0, sink = N+1; int a, b, c; for(int i = 1; i <= M; i++) { scanf("%d%d%d", &a, &b, &c); addEdge(a, b, c, i);//注意是有向边 //addEdge(b, a, c, i); } val = 0; //M条后 其它的边都是虚拟的边 默认ID为0 for(int i = 1; i <= F; i++) { scanf("%d%d", &a, &c); val += c; addEdge(a, sink, c, 0); } addEdge(source, 1, INF, 0);//source 向 城市1建边}bool BFS(int s, int t){ queue<int> Q; memset(dist, -1, sizeof(dist)); memset(vis, false, sizeof(vis)); dist[s] = 0; vis[s] = true; Q.push(s); while(!Q.empty()) { int u = Q.front(); Q.pop(); for(int i = head[u]; i != -1; i = edge[i].next) { Edge E = edge[i]; if(!vis[E.to] && E.cap > E.flow) { dist[E.to] = dist[u] + 1; if(E.to == t) return true; vis[E.to] = true; Q.push(E.to); } } } return false;}int DFS(int x, int a, int t){ if(x == t || a == 0) return a; int flow = 0, f; for(int &i = cur[x]; i != -1; i = edge[i].next) { Edge &E = edge[i]; if(dist[E.to] == dist[x] + 1 && (f = DFS(E.to, min(a, E.cap - E.flow), t)) > 0) { edge[i].flow += f; edge[i^1].flow -= f; flow += f; a -= f; if(a == 0) break; } } return flow;}int Maxflow(int s, int t){ int flow = 0; while(BFS(s, t)) { memcpy(cur, head, sizeof(head)); flow += DFS(s, INF, t); } return flow;}void find_S(int u)//在残量网络里面 找源点能到的S集{ for(int i = head[u]; i != -1; i = edge[i].next) { Edge E = edge[i]; if(vis[E.to]) continue; if(E.cap > E.flow)//不能满流 { vis[E.to] = true; find_S(E.to); } }}int rec[100000+1];//记录最小割里面边的编号void output(){ int ans = 0;//统计要去掉的边数 memset(vis, false, sizeof(vis)); find_S(1);//要从1开始 for(int i = 0; i < edgenum; i+=2)//遍历正向弧 { if(edge[i].ID == 0)//出现ID为0的边 意味着M条实边已经遍历完了 break; if(vis[edge[i].from] && !vis[edge[i].to])//起点在S集 终点不在 rec[ans++] = edge[i].ID;//记录 } printf("%d", ans); for(int i = 0; i < ans; i++) printf(" %d", rec[i]); printf("\n");}int main(){ int t, k = 1; scanf("%d", &t); while(t--) { scanf("%d%d%d", &N, &M, &F); init(); getMap(); printf("Case %d: %d\n", k++, val - Maxflow(source, sink)); output(); } return 0;}
1 0
- hdoj 3251 Being a Hero 【建图后求解最小割 + 输出任意一组最小割里面边 的编号】
- HDOJ 3251 - Being a Hero 构图最小割
- hdu 3251 Being a Hero(最小割,最大权闭包+输出割边)
- hdu 3251 Being a Hero(最小割)
- hdu 3251 Being a Hero 最小割
- 【最小割】HDU 3251 Being a Hero
- hdu 3251 Being a Hero 最小割
- HDU - 3251 Being a Hero(最小割)
- HDU 3251 Being a Hero 网络流 最小割
- Being a Hero (hdu 3251 最小割 好题)
- HDU 3251 Being a Hero(最小割)经典
- HDU 3251 Being a Hero(最小割)
- HDU 3215 Being a Hero(最小割)
- hdoj 2435 There is a war 【求原图最小割已经分成的两个点集 + 枚举两点集里面的点建新边 求残量网络的最大最小割】
- zoj3792--Romantic Value(最大流+最小割,求解割边)
- hdoj 3657 Game 【最小割】
- 【HDU】3251 Being a Hero 最小割边集【注意】
- 求割边最小的最小割
- 关于安装JDK不当--找不到或无法加载主类 com.sun.tools.javac.Main问题
- Python 函数之参数、局部变量
- HDU 1075 What Are You Talking About(map+字符串)
- POJ题目3229 Facer’s string(后缀数组求a串长度为k子串有几个出现在b串)
- Codeforces Round #303 (Div. 2)
- hdoj 3251 Being a Hero 【建图后求解最小割 + 输出任意一组最小割里面边 的编号】
- C++ 指针与引用的区别 小结
- 总结css实现固定和自适应宽度混合的多栏布局实现方法
- LeetCode(260)Single Number III
- 【ssh】struts2中action接收参数的方法
- >>>,>>的区别
- 将二叉查找树转换为有序的双向链表
- 编译Python及相关模块
- LaTeX中加入Matlab中生成的图片