标签:
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 18289 | Accepted: 9968 |
Description
Input
Output
Sample Input
3 4 1 1 1 3 2 2 3 2
Sample Output
2
Hint
解题思路:
http://www.cnblogs.com/lyy289065406/archive/2011/07/30/2121730.html
把方阵看做一个特殊的二分图(以行列分别作为两个顶点集V1、V2,其中| V1|=| V2|)
然后把每行x或者每列y看成一个点,而障碍物(x,y)可以看做连接x和y的边。按照这种思路构图后。问题就转化成为选择最少的一些点(x或y),使得从这些点与所有的边相邻,其实这就是最小点覆盖问题。
再利用二分图最大匹配的König定理:
最小点覆盖数 = 最大匹配数
(PS:最小点覆盖:假如选了一个点就相当于覆盖了以它为端点的所有边,你需要选择最少的点来覆盖图的所有的边。)
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 6 using namespace std; 7 const int MAX = 500 + 10; 8 int g[MAX][MAX],link[MAX],vis[MAX]; 9 int n,V1,V2,k; 10 int dfs(int x) 11 { 12 for(int i = 1; i <= V2; i++) 13 { 14 if(vis[i] == 0 && g[x][i]) 15 { 16 vis[i] = 1; 17 if(link[i] == 0 || dfs(link[i])) 18 { 19 link[i] = x; 20 return true; 21 } 22 } 23 } 24 return false; 25 } 26 int main() 27 { 28 scanf("%d%d", &n,&k); 29 V2 = V1 = n; 30 for(int i = 1; i <= k; i++) 31 { 32 int x,y; 33 scanf("%d%d",&x,&y); 34 g[x][y] = true; 35 36 } 37 int m = 0; 38 memset(link,0,sizeof(link)); 39 for(int i = 1; i <= V1; i++) 40 { 41 memset(vis,0,sizeof(vis)); 42 if(dfs(i)) 43 m++; 44 } 45 printf("%d\n",m); 46 return 0; 47 }
POJ3041Asteroids(最小点覆盖+然而并不是很理解why)
标签:
原文地址:http://www.cnblogs.com/zhaopAC/p/4998961.html