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 }
本文为博主原创文章,未经博主允许不得转载。