棋盘游戏(hdu)

题目大意:在一张棋盘上给定k个点可以放置车,想要在车之间不互相攻击的情况下放置尽可能多的车(假设为x个)。现在定义这样的点为重要点,如果将该点去掉,就不能放下x个车。求k个点中有几个重要点?

题解:对于棋盘问题,可以根据棋盘的行与列建立二分图。在每个棋子的行与列之间连一条边,如果两个棋子不共行也不共列,那么这两条边就没有公共的顶点,那么这样就可以转化为求二分图的最大匹配数。然后我们依次枚举k个点,如果该点去掉之后最大匹配数改变,则该点就是重要点。这样就可以将一个陌生的问题转化为我们数值的匈牙利算法问题。

AC代码

#include<bits/stdc++.h>
using namespace std;
int n, m, k;
const int maxn = 105;
int edge[maxn][maxn], vis[maxn], link[maxn]; //vis[]数组我称为临时预定数组,vis[j] = a表示一轮模拟匹配中,女孩j被男孩a预定了。

int dfs(int l)
{
	for (int r = 1; r <= m; r++)
	{
		if (edge[l][r] && !vis[r])
		{
			vis[r] = 1;
			if (link[r] == -1 || dfs(link[r]))
			{
				link[r] = l;
				return 1;
			}
		}
	}
	return 0;
}
int hungary()
{
	int ans = 0;
	memset(link, -1, sizeof(link));
	for (int i = 1; i <= n; i++)
	{
		memset(vis, 0, sizeof(vis));
		if (dfs(i))ans++;
	}
	return ans;
}
int main()
{
	int T = 1;
	while (scanf("%d%d%d", &n, &m, &k))
	{
		memset(edge, 0, sizeof(edge));
		for (int i = 1; i <= k; i++)
		{
			int x, y;
			cin >> x >> y;
			edge[x][y] = 1;
		}
		int ans = hungary();
		int important = 0;
		for (int i = 1; i <= n; i++)
		{
			for (int j = 1; j <= m; j++)
			{
				if (edge[i][j])
				{
					edge[i][j] = 0;
					if (hungary() != ans)important++;
					edge[i][j] = 1;
				}
			}
		}
		printf("Board %d have %d important blanks for %d chessmen.\n", T++, important, ans);
	}
}

如果觉得对你有帮助那就点个赞吧!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

流浪小林

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值