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;
}

posted @ 2021-07-14 20:31  acmloser  阅读(23)  评论(0编辑  收藏  举报