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 Descriptionharry Potter notices some Death Eaters try to slip into Castle. The Death Eaters hide in the 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 is blocked at least. Inputinput consists of several test cases.
The first line was number of test case.
Each test case, the first line contains the integers n, m, which means the number of nodes and edges of the graph. Each node was numbered 0 to n-1.
Following m lines contains information about edges. Each of the line have four integers u, V, C, D. The first and integers mean and 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
Outputfor each test case: Output the case number and the answer of how many roads is blocked at least.
Sample Input34 50 1 3 00 2 1 01 2 1 11 3 1 12 3 3 16 70 1 1 00 2 1 00 3 1 01 4 1 02 4 1 03 5 1 04 5 2 03 60 1 1 00 1 2 01 1 1 11 2 1 0 1 2 1 02 1 1 1
Sample OutputCase 1:3case 2:2case 3:2
|
Test instructions: There are n points (numbered from 0 to N-1) and m bars, the edge information has four-the start, end point, the cost of destroying the Edge, D, where D is 1 indicates that the edge is bidirectional, and D is a one-way edge when it is 0. Ask you to block 0 and N-1 the minimum number of sides that need to be destroyed under the least cost premise.
Analysis:
1, before the original minimum cut is not the only It is not necessarily the least that the minimum number of cuts to be obtained for the first time. Under the premise of Benquan and equality of cut-edge sets, there may be a minimum cut with a smaller number of edges .
2, no matter how many minimum cut, we ran the original image after the maximum flow, residual network inside the full flow of the edge must belong to one or more of the minimum cut, the corresponding no full flow of the edge must not belong to any one of the minimum cut.
3, so the problem becomes--in all the full flow of the edge of the destruction of the least number of edges to block the path of 0 to N-1, similar to the shortest side of the edge to break the minimum edges to stop the path to the end, but more to the non-shortest roadside (in the subject is not full stream edge) processing.
Ideas:
1, first build diagram, run at the original 0 to N-1 the maximum flow.
2, build a new diagram based on a residual network. Traverse all forward arcs, if full flow change the edge right to 1, otherwise the edge is infinite, pay attention to the reverse arc to initialize the edge information.
3, finally in the new figure to find a 0 to N-1 the smallest cut, is the answer.
AC Code:
#include <cstdio> #include <cstring> #include <algorithm> #include <queue> #define MAXN 1010# Define MAXM 400000+10#define INF 0x3f3f3f3fusing 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].flo W + = 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); The residual network is processed for (int i = 0; i < Edgenum; i+=2) {Edge E = edge[i]; if (E.cap = = E.flow)//Full stream edge change edge right->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;//handles reverse side} printf ("Case%d:%d\n", k++, Maxflow (1, n));//One more min cut is the answer}int Main () {int t; scanf ("%d", &t); while (t--) {scanf ("%d%d", &n, &m); Init (); Getmap (); Solve (); } return 0;}
Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.
Hdoj 3987 Harry Potter and the Forbidden Forest "find the minimum number of sides in all minimum cuts"