50 years, 50 colors HDU - 1498
原题链接
考察:二分图匹配
错误思路:
统计每种颜色的行数和列数,很明显不一定是全去除行(列).
思路:
对于\(mp[i][j]\),如果我们去除了它,要么是去除第\(i\)行,要么是去除第\(j\)列.枚举每一种颜色\(x\),所在坐标\(i,j\),连接边,求最小点覆盖.
时间复杂度\(O(50N^3)\)
Code
#include <iostream>
#include <cstring>
using namespace std;
const int N = 110,M = 55;
int n,k,mp[N][N],idx,match[N],ans[N],h[N];
bool st[N];
struct Road{
int to,ne;
}road[N*N];
bool dfs(int u)
{
for(int i=h[u];~i;i=road[i].ne)
{
int v = road[i].to;
if(st[v]) continue;
st[v] = 1;
if(!match[v]||dfs(match[v]))
{
match[v] = u;
return 1;
}
}
return 0;
}
void add(int a,int b)
{
road[idx].to = b,road[idx].ne = h[a],h[a] = idx++;
}
int main()
{
while(scanf("%d%d",&n,&k)!=EOF&&(n+k))
{
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
scanf("%d",&mp[i][j]);
int cnt =0;
for(int x=1;x<=M-5;x++)
{
idx = 0;
memset(h,-1,sizeof h);
memset(match,0,sizeof match);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(mp[i][j]==x)
add(i,j);
int res = 0;
for(int i=1;i<=n;i++)
{
memset(st,0,sizeof st);
if(dfs(i)) ++res;
}
if(res>k) ans[++cnt] = x;
}
if(!cnt) puts("-1");
else
for(int i=1;i<=cnt;i++)
printf("%d%c",ans[i],cnt==i?'\n':' ');
}
return 0;
}