zoukankan      html  css  js  c++  java
  • 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
    ", -g.solve()) ;
    102     }
    103     return 0;
    104 }
    View Code
  • 相关阅读:
    在C#中使用SQL存储过程说明
    asp.net后台获取html控件值
    SQL字符串操作汇总[记住这个]select substring(quantityperunit,charindex('',quantityperunit)+1,100) as 结果 from products
    分页控件AspnetPager的用法,巩固用
    摆脱Access在.net中中模糊查询,老错的困扰
    基于黑金开发板的秒表verilog hdl程序
    2808 sci 接收中断
    黑金开发板状态机实现的可用按键控制的流水灯
    基于黑金开发板的键盘边沿检测程序
    可以使用键盘实现加减数的数码管的verilog hdl程序(基于黑金开发板)
  • 原文地址:https://www.cnblogs.com/zhanzhao/p/3931826.html
Copyright © 2011-2022 走看看