二分图的行列式匹配。对于每种颜色在行列间找最小点覆盖(即最大匹配),若大于K则记录下来。最后输出即可
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
#define M 105
int mat[M][M];
vector<int> v[M];
int link[M], vis[N];
int n;
int hash_[M];
void init()
{
for( int i = 1; i <= 105; i++ )
{
v[i].clear();
}
}
void f(int x)
{
init();
for( int i = 1; i <= n; i++ )
{
for ( int j = 1; j <= n; j++ )
{
if( mat[i][j] == x )
{
v[i].push_back(j);
v[j].push_back(i);
}
}
}
}
int find( int u )
{
for( int i = 0; i < v[u].size(); i++ )
{
int to = v[u][i];
if( !vis[to] )
{
vis[to] = 1;
if( link[to] == -1 || find( link[to] ) )
{
link[to] = u;
return 1;
}
}
}
return 0;
}
int match()
{
memset( link, -1, sizeof(link) );
int x = 0;
for( int i = 1; i <= n; i++ )
{
memset(vis, 0, sizeof(vis));
x += find(i);
}
return x;
}
int main()
{
int k;
while(~scanf("%d%d", &n, &k) && (n || k))
{
memset( hash_, 0, sizeof(hash_));
for( int i = 1; i <= n; i++ )
{
for ( int j = 1; j <= n; j++ )
{
scanf("%d", &mat[i][j]);
hash_[mat[i][j]]++;
}
}
int ans = 0;
int a[N];
for( int i = 1; i <= 50; i++ )
{
if(hash_[i])
{
f(i);
int x = match();
if( x > k )
{
a[ans++] = i;
}
}
}
if( ans == 0 )
{
printf("-1\n");
continue;
}
else
{
sort(a, a + ans);
printf("%d", a[0]);
for( int i = 1; i < ans; i++ )
{
printf(" %d", a[i]);
}
puts("");
}
}
return 0;
}