zoukankan      html  css  js  c++  java
  • Hdu 3488 Tour (KM 有向环覆盖)

    题目链接:

      Hdu 3488 Tour

    题目描述:

      有n个节点,m条有权单向路,要求用一个或者多个环覆盖所有的节点。每个节点只能出现在一个环中,每个环中至少有两个节点。问最小边权花费为多少?

    解题思路:

      因为每个节点就出现一个,那么每个节点出度和入度都为1咯。我们可以对每个节点u拆点为u,u',分别放在集合X,Y.然后对两个集合进行完备匹配。完备匹配成功以后,每个节点就会有只有一个出度,一个入度的。

    用KM求最小匹配的话,先初始化maps为-INF,然后把各边权值存为负,求出最大值取反即可。

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <iostream>
     4 #include <algorithm>
     5 using namespace std;
     6 const int maxn = 310;
     7 const int INF = 0x3f3f3f3f;
     8 int maps[maxn][maxn], used[maxn], s[maxn], n;
     9 int lx[maxn], ly[maxn];
    10 bool visx[maxn], visy[maxn];
    11 bool Find (int x)
    12 {
    13     visx[x] = 1;
    14     for (int i=1; i<=n; i++)
    15     {
    16         if (!visy[i] && lx[x]+ly[i]==maps[x][i])
    17         {
    18             visy[i] = 1;
    19             if (!used[i] || Find(used[i]))
    20             {
    21                 used[i] = x;
    22                 return true;
    23             }
    24         }
    25         else
    26             s[i] = min (s[i], lx[x] + ly[i] - maps[x][i]);
    27     }
    28     return false;
    29 }
    30 int KM ()
    31 {
    32     memset (used, 0, sizeof(used));
    33     memset (lx, 0, sizeof(lx));
    34     memset (ly, 0, sizeof(ly));
    35     for (int i=1; i<=n; i++)
    36         for (int j=1; j<=n; j++)
    37             lx[i] = max (lx[i], maps[i][j]);
    38     for (int i=1; i<=n; i++)
    39     {
    40         for (int j=1; j<=n; j++)
    41             s[j] = INF;
    42         while (1)
    43         {
    44             memset (visx, 0, sizeof(visx));
    45             memset (visy, 0, sizeof(visy));
    46             if (Find(i))
    47                 break;
    48             int d = INF;
    49             for (int j=1; j<=n; j++)
    50                 if (!visy[j])
    51                     d = min (s[j], d);
    52             for (int j=1; j<=n; j++)
    53             {
    54                 if (visx[j])
    55                     lx[j] -= d;
    56                 if (visy[j])
    57                     ly[j] += d;
    58             }
    59         }
    60     }
    61     int res = 0;
    62     for (int i=1; i<=n; i++)
    63         res += maps[used[i]][i];
    64     return res;
    65 }
    66 int main ()
    67 {
    68     int m, t;
    69     scanf ("%d", &t);
    70     while (t --)
    71     {
    72         scanf("%d %d", &n, &m);
    73         for (int i=1; i<=n; i++)
    74             for (int j=1; j<=n; j++)
    75                 maps[i][j] = -INF;
    76         while (m --)
    77         {
    78             int u, v, s;
    79             scanf ("%d %d %d", &u, &v, &s);
    80             maps[u][v] = max(maps[u][v], -s;
    81         }
    82         printf ("%d
    ", -KM());
    83     }
    84     return 0;
    85 }
    本文为博主原创文章,未经博主允许不得转载。
  • 相关阅读:
    idea-----Intellij IDEA配置tomcat(非maven项目)
    idea-----idea的项目中output框出现乱码
    mysql on windows的安装
    maven配置
    安装tomcat8.5
    jdk11.0.2安装
    idea创建maven web项目
    Mac下使用sshpass让iterm2支持多ssh登录信息保存
    iterm 2快捷键
    java 8 Base64用法
  • 原文地址:https://www.cnblogs.com/alihenaixiao/p/4702762.html
Copyright © 2011-2022 走看看