TourTime limit:3000/1000 MS (java/others) Memory limit:65535/65535 K (java/others) Total submission (s): 2299 Accepted Submission (s): 1151
Problem DescriptionIn The Kingdom of Henryy, there is n (2 <= N <=) cities, with M (M <= 30000) one-way road s connecting them. You is lucky enough to has a chance to has a tour in the kingdom. The route should is designed as:the route should contain one or more loops. (a loop is a route like:a->b->......->p->a.) Every city should is just in one route. A Loop should has at least and cities. In one route, each city should is visited just once. (The only exception is, the first and the last city should are the same and this are visited twice.) The total distance the N roads you has chosen should be minimized.
Inputan integer T in the first line indicates the number of the the test cases. In each test case, the first line contains integers N and M, indicating the number of the cities and the one-way roads . Then M lines followed, each of the line have three integers U, V and W (0 < W <= 10000), indicating that there is a road fro M U to V, with the distance of W. It is guaranteed, at least one valid arrangement of the tour is existed. A Blank line was followed after each test case. Outputfor each test case, output a line with exactly one integer, which are the minimum total distance. Sample Input16 91 2 52 3 53 1 103 4 124 1 84 6 115 4 75 6 96 5 4
Sample Output42
|
With the expense stream g++ able to pass, C + + will time out.
The KM should be very fast, now brush the cost stream, a few days to make a good km.
Test instructions: Gives the cost of a one-way edge of n points m and passes through each side, allowing you to run out of a Hamiltonian ring (except for the starting point, each point can only walk once) the minimum cost. The topic guarantees that there is at least one ring to satisfy the condition, in fact the inference ring simply needs to infer whether it is full flow.
Idea: Split each point I into left point I and right point i+n
1. The super source point is connected to the left point. Capacity is 1 and the cost is 0
2. All right-click Super sinks with a capacity of 1. Fee is 0
3, each one-way edge--the starting point of the left point of the right point of 1, the cost is the right side.
finally run the cost stream.
Pay attention to the processing of the heavy edge, do not go to the heavy cost stream will time out, there are to be submitted with g++. Take the time to fill the AC code of the KM.
Charge Flow AC Code:
#include <cstdio> #include <cstring> #include <queue> #include <stack> #include <vector># Include <algorithm> #define MAXN 400+10#define maxm 70000+10#define INF 0x3f3f3f3fusing namespace Std;struct edge{ int from, to, cap, flow, cost, next;}; Edge Edge[maxm];int HEAD[MAXN], Edgenum;int PRE[MAXN], Dist[maxn];bool vis[maxn];int N, m;int source, Sink;void Init () { Edgenum = 0; Memset (Head,-1, sizeof (head));} void Addedge (int u, int v, int w, int c)//must go heavy!!!{int i; for (i = head[u]; I! = 1; i = edge[i].next) {if (edge[i].to = = v) break; } if (i! =-1) {if (Edge[i].cost > c) edge[i].cost = c, edge[i^1].cost =-C; return; } Edge E1 = {u, V, W, 0, C, Head[u]}; Edge[edgenum] = E1; Head[u] = edgenum++; Edge E2 = {V, u, 0, 0,-C, Head[v]}; Edge[edgenum] = E2; HEAD[V] = edgenum++;} void Getmap () {scanf ("%d%d", &n, &m); int A, b, C; Source = 0, sink = 2 * N + 1; Divide each point I into left point I and right point i+n//Super Source point even left point. Capacity is 1 and the cost is 0//All right-click Super Meeting Point. Capacity is 1, cost 0//One-way edge: Starting point left point the right point is 1, the cost is Benquan for (int i = 1; I <= N; i++) Addedge (source, I, 1, 0),//added GE (i, i + N, 1, 0), Addedge (i + N, sink, 1, 0); while (m--) {scanf ("%d%d%d", &a, &b, &c); Addedge (A, b+n, 1, c); }}bool SPFA (int s, int t) {queue<int> Q; memset (Dist, INF, sizeof (Dist)); Memset (Vis, false, sizeof (VIS)); memset (Pre,-1, sizeof (pre)); Dist[s] = 0; Vis[s] = true; Q.push (s); while (! Q.empty ()) {int u = q.front (); Q.pop (); Vis[u] = false; for (int i = head[u]; i =-1; i = Edge[i].next) {Edge E = Edge[i]; if (dist[e.to] > Dist[u] + e.cost && e.cap > E.flow) {dist[e.to] = Dist[u] + e.cos T Pre[e.to] = i; if (!vis[e.to]) {vis[e.to] = true; Q.push (e.to); }}}} ' return pre[t]! =-1;} void MCMF (int s, int t, int &cost, int &flow) {flow = Cost = 0; while (SPFA (s, t)) {int Min = INF; for (int i = pre[t]; i =-1; i = pre[edge[i^1].to]) {Edge E = Edge[i]; min = min (min, e.cap-e.flow); } for (int i = pre[t]; i =-1; i = pre[edge[i^1].to]) {edge[i].flow + = Min; Edge[i^1].flow = Min; Cost + = Edge[i].cost * Min; } flow + = Min; }}int Main () {int t; scanf ("%d", &t); while (t--) {init (); Getmap (); int cost, flow; MCMF (source, sink, cost, flow); printf ("%d\n", cost); } return 0;}
KM algorithm: Heavy brush
Benquan take negative. Pay attention to the processing of the heavy edges.
AC Code:
#include <cstdio> #include <cstring> #include <algorithm> #define INF 0x3f3f3f3f#define MAXN 210using Namespace Std;int Lx[maxn], Ly[maxn];int map[maxn][maxn];bool VISX[MAXN], visy[maxn];int slack[maxn];int Match[MAXN]; int N, m;void getmap () {for (int i = 1; I <= n; i++) {for (int j = 1; J <= N; j + +) Map[i][j] =-inf; } int A, b, C; while (m--) {scanf ("%d%d%d", &a, &b, &c); if (-C > Map[a][b]) map[a][b] =-C; }}int DFS (int x) {visx[x] = true; for (int y = 1; y <= N; y++) {if (visy[y]) continue; int t = lx[x] + ly[y]-map[x][y]; if (t = = 0) {Visy[y] = true; if (match[y] = =-1 | | DFS (Match[y])) {match[y] = x; return 1; }} else if (Slack[y] > t) slack[y] = t; } return 0;} void KM () {memset (match,-1, sizeof (match)); memset (ly, 0, sizeof (ly)); for (int x = 1; <= N; x + +) {lx[x] =-inf; for (int y = 1; y <= N; y++) lx[x] = max (lx[x], map[x][y]); } for (int x = 1; x <= N; + +) {for (int i = 1; I <= N; i++) slack[i] = INF; while (1) {memset (VISX, False, sizeof (VISX)); Memset (Visy, False, sizeof (Visy)); if (DFS (x)) break; int d = INF; for (int i = 1; I <= N; i++) {if (!visy[i] && slack[i] < d) d = Slack[i]; } for (int i = 1; I <= N; i++) {if (Visx[i]) lx[i]-= D; } for (int i = 1; I <= N; i++) {if (Visy[i]) ly[i] + = D; else Slack[i]-= D; }}} int ans = 0; for (int i = 1; I <= N; i++) ans + = map[match[i]][i]; printf ("%d\n",-ans);} int main () {int t; scanf ("%d", &t); while (t--) {scanf ("%d%d", &n, &m); Getmap (); KM (); } return 0;}
HDOJ 3488 Tour "minimum cost Max Flow" "km algorithm"