题目:http://poj.org/problem?id=3041
题意:在某个n*n的空间内,分布有一些小行星,某人在里面打炮,放一枪后某一行或某一列的行星就都没了,让求最少的打炮数。
然后把每行x或者每列y看成一个点,而障碍物(x,y)可以看做连接x和y的边。按照这种思路构图后。
问题就转化成为选择最少的一些点(x或y),使得从这些点与所有的边相邻,其实这就是最小点覆盖问题。
再利用二分图最大匹配的König定理:最小点覆盖数 = 最大匹配数
现在还是很多地方不会
最小点覆盖:假如选了一个点就相当于覆盖了以它为端点的所有边,你需要选择最少的点来覆盖图的所有的边。
1 #include <iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cstdlib> 5 #include<stack> 6 #include<queue> 7 #include<iomanip> 8 #include<cmath> 9 #include<algorithm> 10 using namespace std; 11 12 int vis[1000],G[510][510],link[1000]; 13 int n; 14 int find(int x) 15 { 16 int i; 17 for(i=1; i<=n; i++) 18 { 19 if(G[x][i]&&!vis[i]) 20 { 21 vis[i]=1; 22 if(link[i]==0||find(link[i])) 23 { 24 link[i]=x; 25 return 1; 26 } 27 } 28 } 29 return 0; 30 } 31 int main() 32 { 33 int k,i,j,x,y,sum; 34 memset(link,0,sizeof(link)); 35 memset(G,0,sizeof(G)); 36 cin>>n>>k; 37 sum=0; 38 for(i=0; i<k; i++) 39 { 40 cin>>x>>y; 41 G[x][y]=1; 42 } 43 for(i=1; i<=n; i++) 44 { 45 memset(vis,0,sizeof(vis)); 46 if(find(i)) 47 sum++; 48 } 49 cout<<sum<<endl; 50 return 0; 51 } 52
参考博客:http://www.cnblogs.com/pony1993/archive/2012/07/25/2607738.html
http://www.cnblogs.com/kuangbin/archive/2012/08/26/2657446.html
http://www.cnblogs.com/E-star/archive/2012/02/16/2354303.html