poj3041_匈牙利算法_二分图最小覆盖点(最大匹配数)

来源:互联网 发布:创盈门窗优化软件 编辑:程序博客网 时间:2024/06/05 18:49

题目链接


这里是不是应该写下什么是匈牙利算法大笑(找到了一个非常容易理解的一个讲解趣味算法),这位大佬已经讲的很详细了(和这我道题雷同二分图最大匹配数)~~~

题意:

在一个n*n的网格中,有k个炸弹吧,每次可以删除一行或者一列,要清除这所有炸弹最少要删除几次。

思路(copy:参考链接):

将每行、每列分别看作一个点,对于case的每一个行星坐标(x,y),将第x行和第y列连接起来,例如对于输入:

(1,1)、(1,3)、(2,2)、(3,2)4点构造图G:


这样,每个点就相当于图G的一条边,消灭所有点=消灭图G的所有边,又要求代价最少,即找到图G上的最少的点使得这些点覆盖了所有边。

v2_used[]是记录是否遍历过v2

v2_link[]是记录v2的y匹配的v1编号x;


#include<stdio.h>#include<string.h>int map[505][505]; int v2_link[10005];int v2_used[10005];int res,v1,v2;bool dfs(int x){int y;for(y=1;y<=v2;y++){if(map[x][y]==1&&!v2_used[y]){v2_used[y]=1;if(v2_link[y]==0||dfs(v2_link[y])){v2_link[y]=x;return true;}}}return false;} void search(){int x;for(x=1;x<=v1;x++){     memset(v2_used,0,sizeof(v2_used)); if(dfs(x))      res++;}   }int main(){   int x,y,i,n,k;   scanf("%d%d",&n,&k);      v1=v2=n;      memset(map,0,sizeof(map));   res=0;     for(i=1;i<=k;i++)   {       scanf("%d%d",&x,&y);    map[x][y]=1;    }   search();      printf("%d\n",res);return 0;}


0 0