题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1498
题解:(hdu2119的强化版)把行和列看成二分图的两部分,每个边只要选一个点就能删除,选择最少的点覆盖所有的边。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXN 102
int mp[MAXN][MAXN],n;
int from[MAXN],used[MAXN];
int cmp(const void *x,const void *y)
{//从小到大
return *(int *)x-*(int *)y;
}
int match(int x,int color)//color当前颜色
{
int i;
for(i=1;i<=n;++i)
{
if(!used[i]&&mp[x][i]==color)
{
used[i]=1;
if(from[i]==-1||match(from[i],color))
{
from[i]=x;
return 1;
}
}
}
return 0;
}
int hungary(int color)
{
int i,sum=0;
memset(from,-1,sizeof(from));
for(i=1;i<=n;++i)
{
memset(used,0,sizeof(used));
if(match(i,color))
sum++;
}
return sum;
}
int main()
{
int i,j,tot,k,cnt;
int ans[52],colors[52],visited[52];
while(scanf("%d %d",&n,&k)&&n)
{
tot=0;
memset(visited,0,sizeof(visited));
for(i=1;i<=n;++i)
{
for(j=1;j<=n;++j)
{
scanf("%d",&mp[i][j]);
if(!visited[mp[i][j]])
{
colors[tot++]=mp[i][j];/颜/保存色
visited[mp[i][j]]=1;
}
}
}
for(i=0,cnt=0;i<tot;++i)
{//对每一种颜色求最大匹配数
if(hungary(colors[i])>k)
ans[cnt++]=colors[i];
}
if(cnt!=0)
{
qsort(ans,cnt,sizeof(ans[0]),cmp);
printf("%d",ans[0]);
for(i=1;i<cnt;++i)
printf(" %d",ans[i]);
printf("\n");
}
else
{
printf("-1\n");
}
}
return 0;
}