题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1498
解题思路:
这题看上去很和二分图的最小顶点覆盖很相似,但关键怎么处理多个不同颜色的气球。
其实就是每次只考虑一个气球,利用一个气球的颜色建立二分图,看它的最小顶点覆盖是否小于k,如果是则说明符合要求。。好吧,至少我没想到。。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<set>
using namespace std;
const int maxn = 105;
int n,m,g[maxn][maxn],color[maxn][maxn];
int match[maxn];
int ans[maxn];
bool vis[maxn];
set<int> Set;
bool dfs(int u)
{
for(int i = 1; i <= n; i++)
{
if(g[u][i] > 0 && vis[i] == false)
{
vis[i] = true;
if(match[i] == -1 || dfs(match[i]))
{
match[i] = u;
return true;
}
}
}
return false;
}
int Max_Match()
{
int ans = 0;
memset(match,-1,sizeof(match));
for(int i = 1; i <= n; i++)
{
memset(vis,false,sizeof(vis));
if(dfs(i))
ans++;
}
return ans;
}
int main()
{
while(scanf("%d%d",&n,&m),n+m)
{
for(int i = 1; i <= n; i++)
for(int j = 1; j <= n; j++)
{
scanf("%d",&color[i][j]);
Set.insert(color[i][j]);
}
int len = 0;
for(set<int>::iterator it = Set.begin(); it != Set.end(); it++)
{
int c = *it;
for(int i = 1; i <= n; i++)
for(int j = 1; j <= n; j++)
{
if(color[i][j] == c)
g[i][j] = 1;
else g[i][j] = 0;
}
if(Max_Match() > m) ans[++len] = c;
}
if(len == 0) printf("-1\n");
else
{
for(int i = 1; i <= len; i++)
printf(i == len ?"%d\n":"%d ",ans[i]);
}
}
return 0;
}