HDU 3488 -- Tour [minimum cost maximum stream & & classic], hdu3488 -- tour

Tour

**Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Others)**

Total Submission (s): 2308 Accepted Submission (s): 1156

Problem DescriptionIn the kingdom of Henryy, there are N (2 <= N <= 200) cities, with M (M <= 30000) one-way roads connecting them. you are lucky enough to have a chance to have a tour in the kingdom. the route shoshould be designed as: The route shoshould contain one or more loops. (A loop is a route like: A-> B-> ...... -> P-> .)

Every city shoshould be just in one route.

A loop shoshould have at least two cities. in one route, each city shoshould be visited just once. (The only exception is that the first and the last city shocould be the same and this city is visited twice .)

The total distance the N roads you have chosen shocould be minimized.

InputAn integer T in the first line indicates the number of the test cases.

In each test case, the first line contains two integers N and M, indicating the number of the cities and the one-way roads. then M lines followed, each line has three integers U, V and W (0 <W <= 10000), indicating that there is a road from U to V, with the distance of W.

It is guaranteed that at least one valid arrangement of the tour is existed.

A blank line is followed after each test case.

OutputFor each test case, output a line with exactly one integer, which is the minimum total distance.

Sample Input

16 91 2 52 3 53 1 103 4 124 1 84 6 115 4 75 6 96 5 4

Sample Output

42

Question:

Given the cost of n vertices and m unidirectional edges and passing through each edge, you can find the minimum cost of passing through a Hamilton ring (except the start point, each point can only go once. The question must have at least one ring to meet the conditions.

Resolution:

You can use the minimum cost stream to write any similar [overwrite the smallest weight of a directed ring.

Because each vertex is required to go at most once in the question, to prevent multiple occurrences, we need to split each vertex I into two points: Left vertex I and right vertex I + n.

The specific figure is as follows:

Source point outset no. 0, all left vertex No. 1 ~ N, right vertex number n + 1 ~ 2 * n, inset No. 2 * n + 1.

(1) The Source Vertex outset has an edge (outset, I, 1, 0) to the vertex I, that is, the Source Vertex and the left vertex build an edge.

(2) If the edge with a valid value of c from I to j points has an edge (I, j + n, 1, c), that is, an edge is created from the left and right points, make sure that each vertex is taken only once.

(3) Each node to the vertex has an edge (I + n, inset, 1, 0), that is, the right vertex and the vertex edge.

In the end, if the maximum stream is = n (full stream), the minimum cost is what we want. Here, the question must be resolved, so I didn't judge the following code.

Why can we solve this problem by using this method? For details, click here:

In addition, the time requirements for this question are strict. For various timeouts, you must add a deduplication request.

# Include <cstdio> # include <cstring> # include <algorithm> # include <queue> # define INF 0x3f3f3f3f # define maxn 500 # define maxm 77000 using namespace std; int n, m; int outset; // super source point int inset; // super sink point struct node {int u, v, cap, flow, cost, next ;}; node edge [maxm]; int head [maxn], cnt; int per [maxn]; // records the int dist [maxn], vis [maxn], and the number of the edge that reaches point I in the augmented path. void init () {cnt = 0; memset (head,-1, sizeof (head);} void add (int u, Int v, int w, int c) {int I; for (I = head [u]; I! =-1; I = edge [I]. next) {node E = edge [I]; if (v = E. v) break;} if (I! =-1) {if (edge [I]. cost> c) edge [I]. cost = c, edge [I ^ 1]. cost =-c; return;} // edge [cnt] = {u, v, w, 0, c, head [u]}, so the write times out, dizzy + _ + node E1 = {u, v, w, 0, c, head [u]}; edge [cnt] = E1; head [u] = cnt ++; node E2 = {v, u, 0, 0,-c, head [v]}; edge [cnt] = E2; head [v] = cnt ++ ;} void getmap () {scanf ("% d", & n, & m); outset = 0; inset = n * 2 + 1; for (int I = 1; I <= n; ++ I) {add (outset, I, 1, 0); add (I + n, Inset, 1, 0) ;}while (m --) {int a, B, c; scanf ("% d", & a, & B, & c); add (a, B + n, 1, c) ;}} bool SPFA (int st, int ed) {queue <int> q; // memset (dist, INF, sizeof (dist); // memset (vis, 0, sizeof (vis); // memset (per,-1, sizeof (per); for (int I = 0; I <= inset; ++ I) {dist [I] = INF; vis [I] = 0; per [I] =-1;} dist [st] = 0; vis [st] = 1; q. push (st); while (! Q. empty () {int u = q. front (); q. pop (); vis [u] = 0; for (int I = head [u]; I! =-1; I = edge [I]. next) {node E = edge [I]; if (dist [E. v]> dist [u] + E. cost & E. cap> E. flow) {// can be relaxed and not full stream dist [E. v] = dist [u] + E. cost; per [E. v] = I; // the ID of the edge that records the arrival of this vertex if (! Vis [E. v]) {vis [E. v] = 1; q. push (E. v) ;}}} return per [ed]! =-1;} void MCMF (int st, int ed, int & cost, int & flow) {flow = 0; // total traffic cost = 0; // total fee while (SPFA (st, ed) {// find the path int mins = INF; for (int I = per [ed]; I! =-1; I = per [edge [I ^ 1]. v]) {mins = min (mins, edge [I]. cap-edge [I]. flow);} // augmented for (int I = per [ed]; I! =-1; I = per [edge [I ^ 1]. v]) {edge [I]. flow + = mins; edge [I ^ 1]. flow-= mins; cost + = edge [I]. cost * mins;} flow + = mins;} int main () {int T; scanf ("% d", & T); while (T --) {init (); getmap (); int cost, flow; MCMF (outset, inset, cost, flow); printf ("% d \ n", cost );} return 0 ;}

Copyright Disclaimer: This article is an original article by the blogger and cannot be reproduced without the permission of the blogger.