原题:http://acm.hdu.edu.cn/showproblem.php?pid=1498
题意:
有一个n*n的矩阵,每个位置用一个数字表示气球的颜色;
每次选择一行或一列爆破颜色相同的气球,若在k次内不能全部爆破则输出该种颜色;
若全部都能爆破则输出--1;
思路:
对于颜色相同的气球(i, j),以i为x集, j为y集,建边;
算最大匹配数,若>k则不能全部爆破;
#include<stdio.h>
#include<string.h>
const int maxn = 110;
int n, k;
int map[maxn][maxn];
bool used[maxn], line[maxn][maxn];
int match[maxn];
int res[maxn];
bool a[55];
bool find(int x)
{
for(int i = 1;i<=n;i++)
{
if(line[x][i] == true && used[i] == false)
{
used[i] = 1;
if(match[i] == 0||find(match[i]))
{
match[i] = x;
return true;
}
}
}
return false;
}
int main()
{
while(scanf("%d%d", &n, &k)!=EOF)
{
if(n == 0 && k == 0)
break;
memset(a, false, sizeof(a));
for(int i = 1;i<=n;i++)
{
for(int j = 1;j<=n;j++)
{
scanf("%d", &map[i][j]);
a[map[i][j]] = true;
}
}
int t = 0;
for(int e = 1;e<=50;e++)
{
int sum = 0;
memset(line, false, sizeof(line));
memset(match, 0, sizeof(match));
if(a[e] == true)
{
a[e] = false;
for(int i = 1;i<=n;i++)
{
for(int j = 1;j<=n;j++)
{
if(map[i][j] == e)
line[i][j] = true;
}
}
}
for(int i = 1;i<=n;i++)
{
memset(used, false, sizeof(used));
if(find(i))
sum++;
}
if(sum>k)
res[++t] = e;
}
if(t == 0)
printf("-1\n");
else
{
for(int i = 1;i<=t;i++)
{
if(i == t)
printf("%d\n", res[i]);
else
printf("%d ", res[i]);
}
}
}
return 0;
}