最小点覆盖 最大独立集

最小点覆盖

在二分图中,找出一个最小的点集,使之覆盖所有的边,这个问题被称为二分图的最小点覆盖。

König定理:

二分图最小点覆盖包含的点数等于这个二分图的最大匹配数。
证明:
1.求出二分图的最大匹配,定义:匹配边为包含在最大匹配里的边,匹配点为与匹配边相连的点。
2.从二分图右部的非匹配点开始,按照:非匹配边->匹配边->非匹配边......(交错路)依次将遍历到的结点打上标记。
3.选取左部标记点和右部未标记点即可构成最小点覆盖。
证明懒得写了

二分图最小点覆盖模型特点(“2要素”):每个边有两个端点,两个端点任选其一即可。

题目:POJ 2226
题解:
显而易见:木板越长越好。
对于一个泥地,要么被横着的木板挡住,要么被竖着的木板挡住。先预处理挡住每个泥地木板编号,将横着的木板作为右部结点,竖着的作为左部端点,连边求出最小点覆盖即为答案。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
const int N = 2505;
const int M = 5000;
int n, m, map[N][N], tot = 0, match[M], tot1 = 0;
int head[N], nextt[M << 1], to[M << 1], cnt = 0;
void add(int x, int y) {
	nextt[++cnt] = head[x];
	to[cnt] = y; head[x] = cnt;
}
struct node {
	int len, row;
} e[N][N];
bool vis[M];
bool dfs(int x) {
	for(int i = head[x]; i; i = nextt[i]) {
		int y = to[i];
		if(vis[y]) continue;
		vis[y] = true;
		if(!match[y] or dfs(match[y])) {
			match[y] = x; return true;
		}
	}
	return false;
}
int main() {
//	freopen("data.in", "r", stdin);
	scanf("%d%d", &n, &m);
	for(int i = 1; i <= n; i++) {
		for(int j = 1; j <= m; j++) {
			char s; cin >> s;
			if(s == '.') map[i][j] = -1;
		}
	}
	tot = 1;
	for(int i = 1; i <= n; i++) {
		for(int j = 1; j <= m;) {
			if(map[i][j] == -1) {
				tot++; 
				while(map[i][j] == -1 && j <= m) j++;
			} else {
				while(map[i][j] != -1 && j <= m) {
					e[i][j].len = tot; j++;
				}
				if(j > m) tot++; 
			}
		}
	}
	tot1 = 1;
	for(int j = 1; j <= m; j++) {
		for(int i = 1; i <= n;) {
			if(map[i][j] == -1) {
				tot1++; 
				while(map[i][j] == -1 && i <= n) i++;
			} else {
				while(map[i][j] != -1 && i <= n) {
					e[i][j].row = tot1; i++;
				}
				if(i > n) tot1++; 
			}
		}
	}
	int ans = 0;
	for(int i = 1; i <= n; i++) {
		for(int j = 1; j <= m; j++) {
			if(e[i])
			add(e[i][j].row, e[i][j].len);
		}
	}
	for(int i = 1; i <= tot1; i++) {
		memset(vis, 0, sizeof(vis));
		if(dfs(i)) ans++;
	}
	printf("%d", ans);
	return 0;
}

最大独立集

在二分图中,找出最大的点集,使其中任意两个点都没有边直接相连,这个点集就是最大独立集

最大独立集 = 点数 - 最大匹配

证明:
显然。
选取最多的点构成独立集 <==> 用最少的点覆盖边,总点数去掉最小点覆盖后剩下的点之间没有边直接相连
证毕。

题目:P3355 骑士共存问题
题解:对棋盘进行黑白染色,分成两部分作为左右部结点,能互相攻击到的格子之间连边(观察可知,一种颜色的格子无法攻击和它颜色相同的格子,所以连完边后构成一张二分图)求出最大独立集即为答案。

posted @ 2020-04-17 13:40  Mcggvc  阅读(319)  评论(0编辑  收藏  举报