hdu1498 50 years, 50 colors--匈牙利算法

原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=1498


题意:一个n*n的矩阵,矩阵的每个格子放一个气球,气球颜色最多50种,编号1---50。对于每种颜色的气球,每次消去一行或者一列的该种颜色气球,问k次操作后,该颜色气球是否还存留,如果存留输出该气球编号。多种颜色气球存留的话,按编号大小升序输出;一个都不存在输出-1。


别人的题解都是最小点覆盖,我没看出来,但是单从匈牙利算法出发,这题还是可以理解的。一个巧妙之处就是match数组的作用,对于当前颜色,消去当前行,发现match[ 列坐标]!=-1的时候,说明该列存有相同颜色气球,那么如果if (dfs(match[v], color))成立,我们就要删除该列,而不是行,这是个转化问题,感觉好菜啊,,,继续努力吧。


#define _CRT_SECURE_NO_DEPRECATE 

#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
#define INF 99999999;
using namespace std;

int n, k;
int a[105][105];
bool color[55];//该颜色是否存在
int match[105];
bool vis[105];

int dfs(int u, int color)
{
	for (int v = 0; v < n; v++)
	{
		if (a[u][v] == color&&!vis[v])
		{
			vis[v] = true;
			if (match[v] == -1 || dfs(match[v], color))
			{
				match[v] = u;
				return 1;
			}
		}
	}
	return 0;
}

int hungarian(int color)
{
	int ans = 0;
	memset(match, -1, sizeof(match));
	for (int i = 0; i < n; i++)
	{
		memset(vis, 0, sizeof(vis));
		ans += dfs(i, color);
	}
	return ans;
}

int main()
{
	while (scanf("%d%d", &n, &k), n || k)
	{
		memset(color, 0, sizeof(color));

		for (int i = 0; i < n; i++)
		{
			for (int j = 0; j < n; j++)
			{
				scanf("%d", &a[i][j]);
				color[a[i][j]] = 1;
			}
		}

		int p[55];//保存不能k次消除完的点
		int tol = 0;
		for (int i = 1; i <= 50; i++)
		{
			if (color[i])//该颜色存在
				if (hungarian(i) > k)//注意匈牙利这里的参数赋值是i,不是color[i]
					p[tol++] = i;//注意是赋值i,不是赋值color[i]
		}

		if (tol == 0)
			printf("-1\n");
		else
		{
			sort(p, p + tol);
			for (int i = 0; i < tol; i++)
				(i == 0) ? printf("%d", p[i]) : printf(" %d", p[i]);
			printf("\n");
		}
	}
	return 0;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值