zoukankan      html  css  js  c++  java
  • Poj 2594 Treasure Exploration (最小边覆盖+传递闭包)

    题目链接:

      Poj 2594 Treasure Exploration

    题目描述:

      在外星上有n个点需要机器人去探险,有m条单向路径。问至少需要几个机器人才能遍历完所有的点,一个点可以被多个机器人经过。

    解题思路:

      一眼看上去是普通的最小边覆盖,但是仔细想后发现如果在原图上进行最大匹配的话,每个点只能经过一次。这样的话对于本题求出的并不是最优解,所以我们要先对原图进行传递闭包处理,然后再进行最大匹配。

    这个题目点数太少H_K和匈牙利算法在空间和时间上并没有什么差,就代码复杂度而言匈牙利算法更有优势。

     1 #include <iostream>//匈牙利算法
     2 #include <cstring>
     3 #include <queue>
     4 #include <cmath>
     5 #include <cstdio>
     6 using namespace std;
     7 
     8 const int maxn = 510;
     9 int maps[maxn][maxn], n, m;
    10 int used[maxn], vis[maxn];
    11 void floyd ()
    12 {
    13     for (int k=1; k<=n; k++)
    14         for (int i=1; i<=n; i++)
    15             for (int j=1; j<=n; j++)
    16                 if (maps[i][k] && maps[k][j])
    17                     maps[i][j] = 1;
    18 }
    19 int Find (int u)
    20 {
    21     for (int i=1; i<=n; i++)
    22     {
    23         if (!vis[i] && maps[u][i])
    24         {
    25             vis[i] = 1;
    26             if (!used[i] || Find(used[i]))
    27             {
    28                 used[i] = u;
    29                 return 1;
    30             }
    31         }
    32     }
    33     return 0;
    34 }
    35 int main ()
    36 {
    37     while (scanf ("%d %d", &n, &m), n||m)
    38     {
    39         memset (maps, 0, sizeof(maps));
    40         while (m --)
    41         {
    42             int u, v;
    43             scanf ("%d %d", &u, &v);
    44             maps[u][v] = 1;
    45         }
    46         floyd ();
    47         memset (used, 0, sizeof(used));
    48         int res = 0;
    49         for (int i=1; i<=n; i++)
    50         {
    51             memset (vis, 0, sizeof(vis));
    52             res += Find(i);
    53         }
    54         printf ("%d
    ", n - res);
    55     }
    56     return 0;
    57 }
      1 #include <iostream>//H_K算法
      2 #include <cstring>
      3 #include <queue>
      4 #include <cmath>
      5 #include <cstdio>
      6 using namespace std;
      7 
      8 const int maxn = 510;
      9 const int INF = 0x3f3f3f3f;
     10 int maps[maxn][maxn], n, m, dx[maxn], dy[maxn];
     11 int vis[maxn], cx[maxn], cy[maxn], dis;
     12 void floyd ()
     13 {
     14     for (int k=1; k<=n; k++)
     15         for (int i=1; i<=n; i++)
     16             for (int j=1; j<=n; j++)
     17                 if (maps[i][k] && maps[k][j])
     18                     maps[i][j] = 1;
     19 }
     20 bool bfs ()
     21 {
     22     queue <int> Q;
     23     dis = INF;
     24     memset (dx, -1, sizeof(dx));
     25     memset (dy, -1, sizeof(dy));
     26     for (int i=1; i<=n; i++)
     27         if (cx[i] == -1)
     28             {
     29                 Q.push(i);
     30                 dx[i] = 0;
     31             }
     32     while (!Q.empty())
     33     {
     34         int u = Q.front();
     35         Q.pop();
     36         if (dx[u] > dis)
     37             break;
     38         for (int i=1; i<=n; i++)
     39         {
     40             if (dy[i]==-1 && maps[u][i])
     41             {
     42                 dy[i] = dx[u] + 1;
     43                 if (cy[i] == -1)
     44                     dis = dy[i];
     45                 else
     46                 {
     47                     dx[cy[i]] = dy[i] +1;
     48                     Q.push (cy[i]);
     49                 }
     50             }
     51         }
     52     }
     53     return dis != INF;
     54 }
     55 int dfs (int u)
     56 {
     57     for (int v=1; v<=n; v++)
     58     {
     59         if (!vis[v] && dx[u]+1==dy[v] && maps[u][v])
     60         {
     61             vis[v] = 1;
     62             if (cy[v]!=-1 && dis==dy[v])
     63                 continue;
     64             if (cy[v]==-1 || dfs(cy[v]))
     65             {
     66                 cx[u] = v;
     67                 cy[v] = u;
     68                 return 1;
     69             }
     70         }
     71     }
     72     return 0;
     73 }
     74 int Max_match ()
     75 {
     76     int res = 0;
     77     memset (cx, -1, sizeof(cx));
     78     memset (cy, -1, sizeof(cy));
     79     while (bfs())
     80     {
     81         memset (vis, 0, sizeof(vis));
     82         for (int i=1; i<=n; i++)
     83             if (cx[i] == -1)
     84                 res += dfs (i);
     85     }
     86     return res;
     87 }
     88 int main ()
     89 {
     90     while (scanf ("%d %d", &n, &m), n||m)
     91     {
     92         memset (maps, 0, sizeof(maps));
     93         while (m --)
     94         {
     95             int u, v;
     96             scanf ("%d %d", &u, &v);
     97             maps[u][v] = 1;
     98         }
     99         floyd ();
    100         printf ("%d
    ", n - Max_match());
    101     }
    102     return 0;
    103 }
    本文为博主原创文章,未经博主允许不得转载。
  • 相关阅读:
    HDU2586 How far away?(tarjan的LCA)
    You Raise Me Up
    POJ2891 Strange Way to Express Integers(中国剩余定理)
    POJ2142 The Balance(扩展欧几里得)
    HDU 1166模仿大牛写的线段树
    NetWord Dinic
    HDU 1754 线段树裸题
    hdu1394 Minimum Inversion Number
    hdu2795 Billboard
    【完全版】线段树
  • 原文地址:https://www.cnblogs.com/alihenaixiao/p/4701117.html
Copyright © 2011-2022 走看看