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", 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", n - Max_match());
101     }
102     return 0;
103 }
时间: 2024-11-03 22:08:29

Poj 2594 Treasure Exploration (最小边覆盖+传递闭包)的相关文章

poj 2594 Treasure Exploration 最少边覆盖+传递闭包

给出一个有向无环图,问最少多少条边就可以覆盖所有的点,很明显的最少路径覆盖问题,但是点可以重复用,这与hungary算法不太一样,我们可以这样处理,假设a要经过b点到c,但是b点已经被访问过,为了保证a顺利到c,就让a直接飞过b到c,也就是说添加一条a到c的边,这其实就是求传递闭包,我们可以通过floyd算法求出.然后ans=n-hungary(). 一开始用了邻接表的最大二分匹配,在求闭包的时候用的dfs,但是超时了,估计是求闭包的时候加边过多导致的,而且还要判断边是否重复,因此在时空复杂度允

POJ 2594 Treasure Exploration(最小路径覆盖变形)

POJ 2594 Treasure Exploration 题目链接 题意:有向无环图,求最少多少条路径能够覆盖整个图,点能够反复走 思路:和普通的最小路径覆盖不同的是,点能够反复走,那么事实上仅仅要在多一步.利用floyd求出传递闭包.然后依据这个新的图去做最小路径覆盖就可以 代码: #include <cstdio> #include <cstring> #include <vector> #include <algorithm> using names

poj 2594 Treasure Exploration (二分匹配)

Treasure Exploration Time Limit: 6000MS   Memory Limit: 65536K Total Submissions: 6558   Accepted: 2644 Description Have you ever read any book about treasure exploration? Have you ever see any film about treasure exploration? Have you ever explored

POJ 2594 —— Treasure Exploration——————【最小路径覆盖、可重点、floyd传递闭包】

Treasure Exploration Time Limit:6000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Submit Status Practice POJ 2594 Description Have you ever read any book about treasure exploration? Have you ever see any film about treasure exploratio

poj 2594 Treasure Exploration(最小路径覆盖/二分最大匹配)

Treasure Exploration Time Limit: 6000MS   Memory Limit: 65536K Total Submissions: 7208   Accepted: 2944 Description Have you ever read any book about treasure exploration? Have you ever see any film about treasure exploration? Have you ever explored

POJ 2594 Treasure Exploration 最小可相交路径覆盖

最小路径覆盖 DAG的最小可相交路径覆盖: 算法:先用floyd求出原图的传递闭包,即如果a到b有路径,那么就加边a->b.然后就转化成了最小不相交路径覆盖问题. 这里解释一下floyd的作用如果1->2->3->4那么1可以到达2,3,4只要需要借助一些点,那么就可以直接把1与2,3,4相连,这就是floyd要做的事. 证明:为了连通两个点,某条路径可能经过其它路径的中间点.比如1->3->4,2->4->5.但是如果两个点a和b是连通的,只不过中间需要经

poj 2594 Treasure Exploration 二分图匹配

点击打开链接题目链接 Treasure Exploration Time Limit: 6000MS   Memory Limit: 65536K Total Submissions: 7215   Accepted: 2947 Description Have you ever read any book about treasure exploration? Have you ever see any film about treasure exploration? Have you eve

POJ 2594 Treasure Exploration【传递闭包+最小路径覆盖】

大意: 有n个点,告诉你一些单向边,问多少条边能把所有的点覆盖[注意点能重复覆盖  比如4->1->2   5->3] 分析: 知识储备: 传递闭包:  所谓传递,可以这么理解,对于节点j如果i能到k并且k能到j那么i能到j,这样用像floyed就能处理出任意两个点能否到达 for(int k = 1; k <= n; k++) { for(int i = 1; i <= n; i++) { if(W[i][k]) { for(int j = 1; j <= n; j+

poj 2594 Treasure Exploration(最小路径覆盖,可重点)

题意:选出最小路径覆盖图中所有点,路径可以交叉,也就是允许路径有重复的点. 分析:这个题的难点在于如何解决有重复点的问题-方法就是使用Floyd求闭包,就是把间接相连的点直接连上边,然后就是求最小路径覆盖了.我来大概解释一下为什么是对的,首先我们要明确,当我们重复利用一个点的时候,一定是有两个比较良好的路径相交了,而二分图是不允许这样的情况存在的,因为那必然存在了一个点有一个以上的出度或者入度了,而怎么避免这个问题呢,看下面的图: 这就是针对这个问题的一个典型的模型,如果使用正常二分图,求得的匹