poj 3020 Antenna Placement(二分图匹配)

来源:互联网 发布:linux 反向映射 编辑:程序博客网 时间:2024/06/03 09:07

一个o能够覆盖相邻的两个*,问最少用多少个o覆盖全图,其实就是最小路径覆盖,可以把相邻的两个*看成一个点,然后就是求二分最大匹配

所求的最小路径覆盖 = |V|-最大独立集 = |V|-最大匹配数。而这题是无向匹配,多算了1倍,所以要除以2

#include<iostream>#include<algorithm>#include<string.h>#include<stack>#include<queue>#include<math.h>#include<cstdio>using namespace std;#define maxn 500int num[maxn][maxn];char s[maxn][maxn];bool map[maxn][maxn];bool vis[maxn]; int link[maxn];int n,m,cnt;bool dfs(int u){for(int i=1;i<=cnt;i++){if(!vis[i] && map[u][i]){vis[i]=1;if(link[i]==-1 || dfs(link[i])){link[i]=u;return true;}}}return false;}int match(){int ans=0;for(int i=1;i<=cnt;i++){memset(vis,0,sizeof(vis));if(dfs(i))ans++;}return ans;}int main(){int t;scanf("%d",&t);while(t--){scanf("%d%d",&n,&m);cnt=0;for(int i=1;i<=n;i++)for(int j=1;j<=m;j++){cin>>s[i][j];if(s[i][j]=='*')num[i][j]=++cnt;}memset(map,0,sizeof(map));for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)if(s[i][j]=='*'){if(i-1>=1 && s[i-1][j]=='*')map[num[i-1][j]][num[i][j]]=1;if(i+1<=n && s[i+1][j]=='*')map[num[i+1][j]][num[i][j]]=1;if(j-1>=1 && s[i][j-1]=='*')map[num[i][j-1]][num[i][j]]=1;if(j+1<=m && s[i][j+1]=='*')map[num[i][j+1]][num[i][j]]=1;}fill(link,link+cnt+1,-1);printf("%d\n",cnt-match()/2);}return 0;}


原创粉丝点击