poj 题目3041 Asteroids (最小点覆盖)

不念不忘少年蓝@ 2022-12-22 02:25 254阅读 0赞

http://poj.org/problem?id=3041

最小覆盖: 最小覆盖要求用最少的点(X集合或Y集合的都行)让每条边都至少和其中一个点关联。

可以证明:最少的点(即覆盖数)=最大匹配数 M
简单的证明如下:
(1)M个是足够的。只需要让它们覆盖最大匹配的M条边,则其它边一定被覆盖(如果有边e不被覆盖,把e加入后得到一个更大的匹配)
(2)M个是必需的,仅考虑形成最大匹配的这M条边,由于它们两两之间没有公共点,因此至少需要M个点才可以把它们覆盖

题意:

问题:
假如你现在正处在一个N*N的矩阵中,这个矩阵里面有K个障碍物,你拥有一把武器,一发弹药一次能消灭一行或一列的障碍物,求最小的弹药消灭全部障碍物
输入为:
N K
接下来有K行,每行包含障碍物的坐标,即r行c列;
如:
3 4
1 1
1 3
2 2
3 2
输出为:
花费最小的弹药数

分析:

对于上面那个数据我们可以用下面的表示,0表示无障碍物,1表示有;
1 0 1
0 1 0
0 1 0

首先,我们利用行跟列做二分图:

20130903125847968

如果第i行的第j列有障碍物,则在图中左边的i行连一条边到右边的j列,上面的数据就对应上图

于是问题就转化成最小点覆盖的问题.求最大匹配即可.

  1. /***************************
  2. # 2013-9-3 12:54:22
  3. # Time: 16MS Memory: 960K
  4. # Author: zyh
  5. # Status: Accepted
  6. ***************************/
  7. #include<stdio.h>
  8. #include<string.h>
  9. int G[505][505],link[505];
  10. bool vis[505];
  11. int n;
  12. bool dfs(int x){
  13. for(int i=1;i<=n;i++){
  14. if(G[x][i]&&!vis[i]){
  15. vis[i] = 1;
  16. if(link[i]==-1 || dfs(link[i])){
  17. link[i] = x;
  18. return 1;
  19. }
  20. }
  21. }
  22. return 0;
  23. }
  24. int main()
  25. {
  26. int i,k,sum,x,y;
  27. scanf("%d%d",&n,&k);
  28. // memset(G,0,sizeof(G)); 一组测试的话,这里不用清零了
  29. memset(link,-1,sizeof(link));
  30. while(k--){
  31. scanf("%d%d",&x,&y);
  32. G[x][y] = 1;
  33. }
  34. for(sum=0,i=1;i<=n;i++){
  35. memset(vis,0,sizeof(vis));
  36. if(dfs(i)) sum++;
  37. }
  38. printf("%d\n",sum);
  39. return 0;
  40. }

发表评论

表情:
评论列表 (有 0 条评论,254人围观)

还没有评论,来说两句吧...

相关阅读