Loading

「学习笔记」二分图基础

二分图

二分图又称作二部图,是图论的一种特殊模型。设 \(G = (V,E)\) 是一个无向图,如果顶点 \(w\) 可以分割成两个互不相交的子集 \((A,B)\),且图中的每一条边 \((i,j)\) 所关联的两个定点分别属于这两个不同的顶点集 \((i \in A, j \in B)\),则称图 \(G\) 为一个二分图。
通俗一点说就是一个图的点分为两部分,每一部分之间的点没有边相连,这就是二分图。
如图:

判断

染色法
给定一张图,把里面的点染为黑白两色,根据给出的边依次进行染色(初始的点没有颜色),如把第一条边的起点染为黑色,那么把与之相连的未染色点染为白色,如果已经染色为白色则跳过,如果已经染为黑色则说明此图不是二分图,全部染完后把终点更新成起点继续染色,直到出现要进行染色的终点与起点颜色相同时返回假,表示不是二分图,或者所有的点染色成功返回真,表示此图为二分图。

int dfs(int u, bool col) {
	if(used[u]) {
		// 如果该点已被染色,判断是否与它相邻的节点颜色不同,即是否与col相同
		if(color[u] == col)	return 1;// 是返回1
		else	return 0;// 否则返回0
	}
	used[u] = true;// 没用过,标记为已用过
	color[u] = col;// 染色
	sum[col]++;// 该种颜色的总数++,即颜色为col的集合的点+1
	int fg = 1;// 初始化fg为1
	for(int i = h[u]; i; i = e[i].nxt) {
		int v = e[i].v;
		fg = (fg && dfs(v, col^1));//判断由它出发的其他节点是否能染色成功
	}
	return fg;
}

例题:P1330 封锁阳光大学
这就是一个判断是否为二分图的简单题目,用 dfs 深搜来判断染色,再处理一下答案就好了

#include<iostream>
#include<cstdio>
#include<cstring>
typedef long long ll;
using namespace std;
const int N = 1e4+5;
const int M = 1e5+5;
int n, m, cnt;
ll ans;
int h[N];
int color[N], used[N];
ll sum[2];

struct edge {
	int u, v, nxt;
} e[M<<1];

inline ll read() {
	ll x = 0;
	int fg = 0;
	char ch = getchar();
	while(ch < '0' || ch > '9') {
		fg |= (ch == '-');
		ch = getchar();
	}
	while(ch >= '0' && ch <= '9') {
		x = (x << 3) + (x << 1) + (ch ^ 48);
		ch = getchar();
	}
	return fg ? ~x + 1 : x;
}

void add(int u, int v) {
	e[++cnt].u = u;
	e[cnt].v = v;
	e[cnt].nxt = h[u];
	h[u] = cnt;
}

int dfs(int u, bool col) {
	if(used[u]) {
		
		if(color[u] == col)	return 1;
		else	return 0;
	}
	used[u] = true;
	color[u] = col;
	sum[col]++;
	int fg = 1;
	for(int i = h[u]; i; i = e[i].nxt) {
		int v = e[i].v;
		fg = (fg && dfs(v, col^1));
	}
	return fg;
}

int main() {
	memset(color,0,sizeof color);
	n=read(), m=read();
	for(int i = 1; i <= m; ++i) {
		int x = read(), y = read();
		add(x, y);
		add(y, x);
	}
	for(int i = 1; i <= n; ++i)	{
		if(used[i])	continue;
		sum[0] = sum[1] = 0;
		if(!dfs(i, 0)) {
			printf("Impossible\n");
			return 0;
		}
		ans += min(sum[0], sum[1]);
	}
	printf("%lld\n", ans);
	return 0;
}
posted @ 2022-08-08 06:44  yi_fan0305  阅读(49)  评论(0编辑  收藏  举报