HDU 3987 Harry Potter and the Forbidden Forest (minimum cut edge in the minimum cut) Classic
Harry Potter and the Forbidden ForestTime Limit: 5000/3000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission (s): 1791 Accepted Submission (s): 596
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.
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 The 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 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
1000 <= n <=
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
34 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 01 2 1 02 1 1 1
Sample Output
Case 1: 3Case 2: 2Case 3: 2
Author aMR @ WHU
Source 2011 Multi-University Training Contest 15-Host by WHU
Idea: we know that the minimum cut is not unique. here we need to find the minimum cut with the minimum cut edge. The best practices are as follows:
First:
W = w * (E + 1) + 1 during edge creation;
In this way, the maximum stream maxflow/(E + 1) and the minimum number of cut edges maxflow % (E + 1) are obtained)
The principle is very simple. If the first two cut edges are all the least cut, the maximum flow is equal.
However, after edge weight transformation, only the smaller number of edges is the minimum cut.
Multiplication (E + 1) is used to ensure that the number of edges is the remainder after superposition, so as not to affect the result of minimum cut.
Second:
After creating a graph and getting the maximum flow, if the edge in the graph is full, it indicates that this edge is the edge on the smallest cut.
Create a new graph. The principle is: Change the full stream edge to the one with the capacity, and change the full stream edge to the INF capacity edge (the changed edge is a positive edge). Then, the maximum stream is the answer.
/* Maximum stream: SAP algorithm. The difference from ISAP is that preprocessing is not required */# include
# Include
# Include
# Define deusing namespace std; # define captype intconst int MAXN = 1010; // the total number of points const int MAXM = 400010; // The total number of sides const int INF = 1 <30; struct EDG {int to, next; captype cap, flow;} edg [MAXM]; int eid, head [MAXN]; int gap [MAXN]; // The number of each distance (or height) Point int dis [MAXN]; // The shortest distance between each point and the end eNode int cur [MAXN]; // cur [u] indicates that starting from the u point can flow through the cur [u] side int pre [MAXN]; void init () {eid = 0; memset (head, -1, sizeof (head);} // three parameters with a directed edge, four parameters without a directed edge void addEdg (int u, int v, captype c, captype rc = 0) {edg [eid]. to = v; edg [eid]. next = head [u]; edg [eid]. cap = c; edg [eid]. flow = 0; head [u] = eid ++; edg [eid]. to = u; edg [eid]. next = head [v]; edg [eid]. cap = rc; edg [eid]. flow = 0; head [v] = eid ++;} captype maxFlow_sap (int sNode, int eNode, int n) {// n indicates the total number of points including the Source and Sink points, memset (gap, 0, sizeof (gap); memset (dis, 0, sizeof (dis); memcpy (cur, head, sizeof (head )); pre [sNode] =-1; gap [0] = n; captype ans = 0; // maximum stream int u = sNode; while (dis [sNode]
Edg [I]. cap-edg [I]. flow) {Min = edg [I]. cap-edg [I]. flow; inser = I;} for (int I = pre [u]; I! =-1; I = pre [edg [I ^ 1]. to]) {edg [I]. flow + = Min; edg [I ^ 1]. flow-= Min; // flow of the reflux edge} ans + = Min; u = edg [inser ^ 1]. to; continue;} bool flag = false; // judge whether int v can flow to adjacent points from the u point; for (int I = cur [u]; I! =-1; I = edg [I]. next) {v = edg [I]. to; if (edg [I]. cap-edg [I]. flow> 0 & dis [u] = dis [v] + 1) {flag = true; cur [u] = pre [v] = I; break ;}} if (flag) {u = v; continue;} // if no adjacent vertex of the stream is found above, the distance (or height) of the starting point u is changed) + 1 int Mind = n; for (int I = head [u]; I! =-1; I = edg [I]. next) if (edg [I]. cap-edg [I]. flow> 0 & Mind> dis [edg [I]. to]) {Mind = dis [edg [I]. to]; cur [u] = I;} gap [dis [u] --; if (gap [dis [u] = 0) return ans; // when the distance of dis [u] is absent, it is impossible to find an augmented stream path from the source point. // there is only one distance between the sink point and the current point, then, from the source point to the sink point will inevitably pass through the current point. However, if the current point fails to find the point that can flow, it will inevitably cut off dis [u] = Mind + 1; // If a adjacent vertex that can be streamed is found, the distance between the adjacent vertex is + 1. If not, the distance is n + 1 gap [dis [u] ++; if (u! = SNode) u = edg [pre [u] ^ 1]. to; // return an edge} return ans;} int main () {int T, _ cas = 0, n, m, u, v, c, d; scanf (% d, & T); while (T --) {init (); scanf (% d, & n, & m); int vs = 0, vt = n-1; for (int I = 0; I