hdoj 3987 Harry Potter and the Forbidden Forest 【求所有最小割里面 最少的边数】
2015-08-30 11:57
465 查看
Harry Potter and the Forbidden ForestTime Limit: 5000/3000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 1802 Accepted Submission(s): 602 Problem Description Harry Potter notices some Death Eaters try to slip into Castle. The Death Eaters hide in the most depths of Forbidden Forest. Harry need stop them as soon as. The Forbidden Forest is mysterious. It consists of N nodes numbered from 0 to N-1. All of Death Eaters stay in the node numbered 0. The position of Castle is node n-1. The nodes connected by some roads. Harry need block some roads by magic and he want to minimize the cost. But it’s not enough, Harry want to know how many roads are blocked at least. Input Input consists of several test cases. The first line is number of test case. Each test case, the first line contains two integers n, m, which means the number of nodes and edges of the graph. Each node is numbered 0 to n-1. Following m lines contains information about edges. Each line has four integers u, v, c, d. The first two integers mean two endpoints of the edges. The third one is cost of block the edge. The fourth one means directed (d = 0) or undirected (d = 1). Technical Specification 1. 2 <= n <= 1000 2. 0 <= m <= 100000 3. 0 <= u, v <= n-1 4. 0 < c <= 1000000 5. 0 <= d <= 1 Output For each test case: Output the case number and the answer of how many roads are blocked at least. Sample Input 3 4 5 0 1 3 0 0 2 1 0 1 2 1 1 1 3 1 1 2 3 3 1 6 7 0 1 1 0 0 2 1 0 0 3 1 0 1 4 1 0 2 4 1 0 3 5 1 0 4 5 2 0 3 6 0 1 1 0 0 1 2 0 1 1 1 1 1 2 1 0 1 2 1 0 2 1 1 1 Sample Output Case 1: 3 Case 2: 2 Case 3: 2 |
分析:
1,在原图最小割不唯一的前提下,第一次求出的最小割的边数未必是最少的。在割边集的边权和相等的前提下,可能存在一个边数更少的最小割。
2,不管有多少个最小割,我们在原图跑一次最大流之后,残量网络里面满流的边一定是属于某个或多个最小割的,相应的没有满流的边一定不属于任何一个最小割。
3,这样问题就变成——在所有满流的边中破坏最少的边数来阻断0到N-1的路径,类似在最短路的边中破坏最少的边来阻断起点到终点的路径,只是多了对非最短路边(在本题中是非满流边)的处理。
思路:
1,先建图,在原图跑一次0到N-1的最大流。
2,以残量网络为基础构建新图。遍历所有正向弧,若满流则更改边权为1,否则边权为无穷大,注意对反向弧要初始化边的信息。
3,最后在新图求一次0到N-1的最小割,就是答案。
AC代码:
#include <cstdio> #include <cstring> #include <algorithm> #include <queue> #define MAXN 1010 #define MAXM 400000+10 #define INF 0x3f3f3f3f using namespace std; struct Edge { int from, to, cap, flow, next; }; Edge edge[MAXM]; int head[MAXN], cur[MAXN], edgenum; int dist[MAXN]; bool vis[MAXN]; int N, M; void init() { edgenum = 0; memset(head, -1, sizeof(head)); } void addEdge(int u, int v, int w) { Edge E1 = {u, v, w, 0, head[u]}; edge[edgenum] = E1; head[u] = edgenum++; Edge E2 = {v, u, 0, 0, head[v]}; edge[edgenum] = E2; head[v] = edgenum++; } void getMap() { int a, b, c, d; while(M--) { scanf("%d%d%d%d", &a, &b, &c, &d); a++, b++; addEdge(a, b, c); if(d) addEdge(b, a, c); } } 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; } int k = 1; void solve() { Maxflow(1, N); //对残量网络 进行处理 for(int i = 0; i < edgenum; i+=2) { Edge E = edge[i]; if(E.cap == E.flow)//满流的边 改变边权->1 { edge[i].cap = 1; edge[i].flow = 0; } else { edge[i].cap = INF; edge[i].flow = 0; } edge[i^1].cap = edge[i^1].flow = 0;//处理反向边 } printf("Case %d: %d\n", k++, Maxflow(1, N));//再求一次最小割就是答案 } int main() { int t; scanf("%d", &t); while(t--) { scanf("%d%d", &N, &M); init(); getMap(); solve(); } return 0; }
相关文章推荐
- POJ 1006 Biorhythms
- windows C++ 多任务并发执行设计
- PCIE协议解析 synopsys IP Power Management Capability 读书笔记(10)
- 自定义控件出属性设置
- xmu 1018 零零漆的作
- 借贷宝有多少人看得懂?借贷宝系统崩溃分析
- BZOJ 1009: [HNOI2008]GT考试( dp + 矩阵快速幂 + kmp )
- Gym 100345H Settling the Universe Up
- scala 第12讲 继承 构造
- [leetcode] 71.Simplify Path
- Codeforces掉分记 round318(div2)
- Ubuntu下Java开发环境搭建(eclipse)
- 如何实现访问同一域名,手机和电脑跳转的不一样
- redis执行了flushdb或者flushall之后的“后悔药”操作
- Java链接SqlServer数据库
- STL源码剖析 [容器](五)[stl_stack.h]
- centos7环境下mariadb的主从复制
- Linux 进程(一):环境及其控制
- 薛定谔把妹法
- 已有 JS 模块化和打包方案收集