题意:
在一个n*n的矩阵中(n<=100)..每个格子放了一种颜色的气球(颜色用数字1~50表示)...每次的操作是消除一行或者一列颜色相同的气球.问经过k次操作..哪些颜色的气球还存在...
题解:
每种颜色分开来求...做边(x,y)....由于对于一个气球(x,y)..只要它x被用了或者y被用了..那么这个气球也就消除了...题目转化为最少要用多少个点..使得所有的边都覆盖..也就是经典的二分图最小点覆盖问题...等价为求二分图的最大匹配数...
Program:
#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<cmath>
#include<stack>
#include<queue>
#define ll long long
#define MAXN 105
using namespace std;
int n,match[MAXN];
bool arc[MAXN][MAXN],inmap[MAXN],used[MAXN],s[MAXN][MAXN];
bool dfs(int x)
{
int i;
for (i=1;i<=n;i++)
if (arc[x][i] && !used[i])
{
used[i]=true;
if (!match[i] || dfs(match[i]))
{
match[i]=x;
return true;
}
}
return false;
}
int getmax()
{
int sum=0;
memset(match,0,sizeof(match));
for (int i=1;i<=n;i++)
{
memset(used,false,sizeof(used));
sum+=dfs(i);
}
return sum;
}
int main()
{
int i,j,k,ans;
bool f;
while (~scanf("%d%d",&n,&k) && n)
{
memset(inmap,false,sizeof(inmap));
for (i=1;i<=n;i++)
for (j=1;j<=n;j++)
scanf("%d",&s[i][j]),inmap[s[i][j]]=true;
f=false;
for (int t=1;t<=50;t++)
if (inmap[t])
{
memset(arc,false,sizeof(arc));
for (i=1;i<=n;i++)
for (j=1;j<=n;j++)
if (s[i][j]==t) arc[i][j]=true;
if (getmax()>k)
{
if (!f) printf("%d",t);
else printf(" %d",t);
f=true;
}
}
if (!f) printf("-1");
printf("\n");
}
return 0;
}