您的位置:首页 > 其它

POJ 3041 Asteroids(二分匹配-hungary)

2015-12-31 13:27 477 查看
Description

有一个n*n的方阵,方阵上有k个障碍物,每一次可以消除一行或者一列上所有的障碍物,问最少需要几次能够消除所有的障碍物

Input

第一行为两个整数n和k表示矩阵行列数和障碍物数量,之后k行每行两个整数i和j表示该障碍物处于第i行第j列

Output

输出最少几次才能消除所有障碍物

Sample Input

3 4

1 1

1 3

2 2

3 2

Sample Output

2

Solution

二分匹配,将每行看作一排点,每列看作一排点,对于每个障碍物(i,j),从第一排点的i到第二排点的j建边,建完图后我们需要找最少的点覆盖所有的边,问题转化为求这张图的最小点覆盖,即最大匹配数

Code

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
#define maxn 555
int uN,vN;//u,v数目
int g[maxn][maxn];//编号是0~n-1的
int linker[maxn];
bool used[maxn];
bool dfs(int u)
{
int v;
for(v=0;v<vN;v++)
if(g[u][v]&&!used[v])
{
used[v]=true;
if(linker[v]==-1||dfs(linker[v]))
{
linker[v]=u;
return true;
}
}
return false;
}
int hungary()
{
int res=0;
int u;
memset(linker,-1,sizeof(linker));
for(u=0;u<uN;u++)
{
memset(used,0,sizeof(used));
if(dfs(u))  res++;
}
return res;
}
int main()
{
int n,k;
while(~scanf("%d%d",&n,&k))
{
memset(g,0,sizeof(g));
uN=vN=n;
while(k--)
{
int x,y;
scanf("%d%d",&x,&y);
g[x-1][y-1]=1;
}
int ans=hungary();
printf("%d\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: