标签:number fast style inpu pre wan points ant 传递
题目链接:https://vjudge.net/problem/POJ-2594
Time Limit: 6000MS | Memory Limit: 65536K | |
Total Submissions: 9005 | Accepted: 3680 |
Description
Input
Output
Sample Input
1 0 2 1 1 2 2 0 0 0
Sample Output
1 1 2
Source
题解:
求最小路径覆盖。但与以往不同的是:一个点可以在多条路径上,即一个点可以被走多次,那怎么办呢?
利用Flyod算法求出传递闭包:如果A可以间接走到B,那么我们就直接把AB连起来。
这样,我们就可以按照常规的方法去求最小路径覆盖了。
代码如下:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 #include <string> 6 #include <vector> 7 #include <map> 8 #include <set> 9 #include <queue> 10 #include <sstream> 11 #include <algorithm> 12 using namespace std; 13 const int INF = 2e9; 14 const int MOD = 1e9+7; 15 const int MAXN = 500+10; 16 17 int n; 18 int M[MAXN][MAXN], link[MAXN]; 19 bool vis[MAXN]; 20 21 bool dfs(int u) 22 { 23 for(int i = 1; i<=n; i++) 24 if(M[u][i] && !vis[i]) 25 { 26 vis[i] = true; 27 if(link[i]==-1 || dfs(link[i])) 28 { 29 link[i] = u; 30 return true; 31 } 32 } 33 return false; 34 } 35 36 int hungary() 37 { 38 int ret = 0; 39 memset(link, -1, sizeof(link)); 40 for(int i = 1; i<=n; i++) 41 { 42 memset(vis, 0, sizeof(vis)); 43 if(dfs(i)) ret++; 44 } 45 return ret; 46 } 47 48 void Flyod() 49 { 50 for(int k = 1; k<=n; k++) 51 for(int i = 1; i<=n; i++) 52 for(int j = 1; j<=n; j++) 53 M[i][j] = M[i][j]|(M[i][k]&&M[k][j]); 54 } 55 56 int main() 57 { 58 int m; 59 while(scanf("%d%d", &n, &m) && (n||m)) 60 { 61 memset(M, false, sizeof(M)); 62 for(int i = 1; i<=m; i++) 63 { 64 int u, v; 65 scanf("%d%d", &u, &v); 66 M[u][v] = true; 67 } 68 69 Flyod(); //求出传递闭包 70 int cnt = hungary(); 71 printf("%d\n", n-cnt); 72 } 73 }
POJ2594 Treasure Exploratio —— 最小路径覆盖 + 传递闭包
标签:number fast style inpu pre wan points ant 传递
原文地址:http://www.cnblogs.com/DOLFAMINGO/p/7818446.html