HDU 3488 Tour【多个环的并】

大意:告诉你一些国家和一些单项路,每条路连接两个国家,告诉你之间的距离,现在要使每个国家都在一个环中

求最小距离

 

分析:这是做过的第二个多个环的并的问题

每个点的入读和出度都为1

把n个点拆点

由于二分图最优匹配的性质可知每个点都会出现在匹配中

相当于每个点出现一次

左边为出度点  有边为入读点

 

值得注意的是两个国家可能会有多条路

要选取最短的

----想起东北赛死在这上边了   ----全都是泪啊

 

代码:

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <vector>
  5 #include <algorithm>
  6 using namespace std;
  7 
  8 const int maxn = 205;
  9 const int INF = 1000000000;
 10 
 11 struct KM {
 12     int n;
 13     vector<int> G[maxn];
 14     int W[maxn][maxn];
 15     int Lx[maxn], Ly[maxn];
 16     int Left[maxn];
 17     bool S[maxn], T[maxn];
 18 
 19     void init(int n) {
 20         this -> n = n;
 21         for(int i = 0; i <= n; i++) G[i].clear();
 22         memset(W, 0, sizeof(W));
 23     }
 24 
 25     void AddEdge(int u, int v, int w) {
 26         if(W[u][v] == 0) {
 27             G[u].push_back(v);
 28             W[u][v] = -w;
 29         } else if(w < - W[u][v]) {
 30             W[u][v] = -w;
 31         }
 32     }
 33 
 34     bool match(int u) {
 35         S[u] = true;
 36         for(int i = 0; i < G[u].size(); i++) {
 37             int v = G[u][i];
 38             if(Lx[u] + Ly[v] == W[u][v] && !T[v]) {
 39                 T[v] = true;
 40                 if(Left[v] == -1 || match(Left[v])) {
 41                     Left[v] = u;
 42                     return true;
 43                 }
 44             }
 45         }
 46         return false;
 47     }
 48 
 49     void update() {
 50         int a = INF;
 51         for(int u = 1; u <= n; u++) if(S[u])
 52             for(int i = 0; i < G[u].size(); i++) {
 53                 int v = G[u][i];
 54                 if(!T[v]) a = min(a, Lx[u] + Ly[v] - W[u][v]);
 55             }
 56         for(int i = 1; i <= n; i++) {
 57             if(S[i]) Lx[i] -= a;
 58             if(T[i]) Ly[i] += a;
 59         }
 60     }
 61 
 62     int solve() {
 63         for(int i = 1; i <= n; i++) {
 64             Left[i] = -1;
 65             Ly[i] = 0;
 66             Lx[i] = 0;
 67             for(int  j = 1; j <= n; j++) {
 68                 if(W[i][j] != INF) {
 69                     Lx[i] = max(Lx[i], W[i][j]);
 70                 }
 71             }
 72         }
 73         for(int u = 1; u <= n; u++) {
 74             for(; ;) {
 75                 for(int i = 1; i <= n; i++) S[i] = T[i] = false;
 76                 if(match(u)) break; else update();
 77             }
 78         }
 79         int ans = 0;
 80         for(int i = 1; i <= n; i++) {
 81             ans += Lx[i] + Ly[i];
 82         }
 83         return ans;
 84     }
 85 };
 86 
 87 KM g;
 88 
 89 int main() {
 90     int t;
 91     int n, m;
 92     int u, v, w;
 93     scanf("%d",&t);
 94     while(t--) {
 95         scanf("%d %d",&n, &m);
 96         g.init(n);
 97         while(m--) {
 98             scanf("%d %d %d",&u, &v, &w);
 99             g.AddEdge(u, v, w );
100         }
101         printf("%d\n", -g.solve()) ;
102     }
103     return 0;
104 }
View Code

 

posted @ 2014-08-23 22:04  悠悠我心。  阅读(146)  评论(0编辑  收藏  举报