2199. 骑士共存问题(最小割,最大权独立集,二分图)

活动 - AcWing

在一个 n∗n 个方格的国际象棋棋盘上,马(骑士)可以攻击的棋盘方格如图所示。

棋盘上某些方格设置了障碍,骑士不得进入。

QQ截图20200727153405.png

对于给定的 n∗n个方格的国际象棋棋盘和障碍标志,计算棋盘上最多可以放置多少个骑士,使得它们彼此互不攻击。

输入格式

第一行有 2 个正整数 n 和 m,分别表示棋盘的大小和障碍数。

接下来的 m 行给出障碍的位置。每行 2 个正整数,表示障碍的方格坐标。

输出格式

输出可以共存的最大骑士数量。

数据范围

1≤n≤200,
0≤m<n2

输入样例:
3 2
1 1
3 3
输出样例:
5

解析: 

本题是要求放最多的马使得所有马不会相互攻击,如果将所有能相互攻击的马之间连一条边,将所有奇数格作为左部节点,将所有偶数格作为右部节点,这就是一个二分图,且要求选中的点之间都不存在边,也就是求二分图的最大独立集,可以用匈牙利算法来求。

但是本题的数据比较大,用匈牙利算法会被卡常数,因此需要用更快的算法实现,可以用网络流求最大权独立集的方法来求,而 dinic 算法比匈牙利算法快很多,不用担心超时。

最大权独立集 = 总权值 − 最小权点覆盖集,因此我们需要求出最小权点覆盖集,用固定做法就行,从源点向所有左部节点连一条容量是权值的边,从所有右部节点向汇点连一条容量是权值的边,左部节点和右部节点之间的边容量是 +∞。最小割就是最小权点覆盖。

本题每个点是没有权值的,求的也是最大独立集的点数,因此可以认为每个点的权值都是 1。这样就能求出最小点覆盖的点数,对应求出最大独立集的点数,两者是互补的。

#include<iostream>
#include<string>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<utility>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<math.h>
#include<map>
#include<sstream>
#include<deque>
#include<unordered_map>
#include<unordered_set>
#include<bitset>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> PII;
const int N = 4e4 + 10, M = (N*8+2*N) * 2 + 10, INF = 0x3f3f3f3f;
int n, m, S, T;
int h[N], e[M], f[M], ne[M], idx;
int q[N], d[N], cur[N];
bool g[210][210];

void add(int a, int b, int c) {
	e[idx] = b, f[idx] = c, ne[idx] = h[a], h[a] = idx++;
	e[idx] = a, f[idx] = 0, ne[idx] = h[b], h[b] = idx++;
}

int get(int a, int b) {
	return (a - 1) * n + b;
}

bool bfs() {
	int hh = 0, tt = 0;
	memset(d, -1, sizeof d);
	q[0] = S, d[S] = 0, cur[S] = h[S];
	while (hh <= tt) {
		int t = q[hh++];
		for (int i = h[t]; i != -1; i = ne[i]) {
			int j = e[i];
			if (d[j] == -1 && f[i]) {
				d[j] = d[t] + 1;
				cur[j] = h[j];
				if (j == T)return 1;
				q[++tt] = j;
			}
		}
	}
	return 0;
}

int find(int u, int limit) {
	if (u == T)return limit;
	int flow = 0;
	for (int i = cur[u]; i != -1 && flow < limit; i = ne[i]) {
		int j = e[i];
		cur[u] = i;
		if (d[j] == d[u] + 1 && f[i]) {
			int t = find(j, min(f[i], limit - flow));
			if (!t)d[j] = -1;
			f[i] -= t, f[i ^ 1] += t, flow += t;
		}
	}
	return flow;
}

int dinic() {
	int ret = 0, flow = 0;
	while (bfs())while (flow = find(S, INF))ret += flow;
	return ret;
}

int main() {
	cin >> n >> m;
	memset(h, -1, sizeof h);
	S = 0, T = n * n + 1;
	for (int i = 1, a, b; i <= m; i++) {
		scanf("%d%d", &a, &b);
		g[a][b] = 1;
	}
	int tot = 0;
	int dx[] = { -1,-2,-2,-1,1,2,2,1 }, dy[] = { -2,-1,1,2,2,1,-1,-2 };
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= n; j++) {
			if (g[i][j])continue;
			if (i + j & 1) {
				add(S, get(i, j), 1);
				for (int k = 0; k < 8; k++) {
					int x = i + dx[k], y = j + dy[k];
					if (x > 0 && x <= n && y > 0 && y <= n&&!g[x][y]) {
						add(get(i, j), get(x, y), INF);
					}
				}
			}
			else add(get(i, j), T, 1);
			tot++;
		}
	}
	cout << tot - dinic() << endl;
	return 0;
}

  • 7
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
回答: eNSP和HCL在兼容共存方面需要考虑它们各自的版本和Oracle VM VirtualBox的版本。eNSP对VM VirtualBox的要求不是很高,一般5.2.44及以上版本就可以。而在Windows系统中,推荐使用win 7专业版或win 10专业版。在win10家庭版中,HCL (3.0.1)和eNSP (V100R003C00SPC100)可以搭配上Oracle VM VirtualBox虚拟机5.2.44版本共存。安装步骤如下:先安装H3CHCL (3.0.1)或Huawei eNSP (V100R003C00SPC100),注意安装目录不要出现中文。这两个工具包的安装顺序不重要,但需要特别注意eNSP安装时还需要安装Winshark和winPcap,尽量选择版本匹配度高的。然后安装VirtualBox虚拟机5.2.44,如果HCL (3.0.1)或eNSP (V100R003C00SPC100)安装包里面自带了VirtualBox虚拟机,则不需要勾选安装那一栏。\[2\]\[3\] #### 引用[.reference_title] - *1* *2* [Win11、10下安装eNSP&HCL5.9.0,解决兼容问题](https://blog.csdn.net/SwaggyXin/article/details/127221401)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [eNSP和HCL兼容共存问题](https://blog.csdn.net/weixin_48306132/article/details/128052877)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值