二分图判断(交叉染色)

二分图又称二部图。

二分图是无向图

设G=(V,E)是一个无向图。如顶点集V可分割为两个互不相交的子集,并且图中每条边依附的两个顶点都分属两个不同的子集。

例如这就是一个二分图。 大概就是把顶点分成两堆,每堆内部没有边。

无向图G为二分图的充分必要条件是,G至少有两个顶点, 且其所有回路的长度均为偶数。

最大独立点集:在二分图中,求最少的点集,使得任意两个点之间没有直接边连接。

最小点覆盖:在二分图中,求最少的点集,使得每一条边至少都有端点在这个点集中。

二分图判断:二分图染色。

给一个无向图。要给图上每个顶点染色,并且使任意相邻的顶点染色不同。并且最多用两种颜色。

如果可以进行二分图染色,证明是一个二分图。

如果可以染色,就是如上图,把每一个颜色放入一个堆,就构成了二分图。

模板:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;

const int MAX_V = 205;

vector<int> G[MAX_V];	// 图
int V;					// 顶点数
int color[MAX_V];		// 顶点i的颜色 1 或 -1

// 把顶点染成1或-1
bool dfs(int v, int c)
{
	color[v] = c; // 把顶点v染成颜色c
	for (int i = 0; i < G[v].size(); ++i) {
		if (color[G[v][i]] == c) return false;
		if (color[G[v][i]] == 0 && !dfs(G[v][i], -c)) return false;
	}
	return true;
}

void solve()
{
	for (int i = 0; i < V; ++i) {
		if (color[i] == 0) {
			if (!dfs(i, 1)) {
				puts("No");
				return ;
			}
		}
	}
	puts("Yes");
}

int main()
{
    int E;
    while (scanf("%d%d", &V, &E) == 2) {
		int a, b;
		for (int i = 0; i < V; ++i) G[i].clear();
		memset(color, 0, sizeof color);
		for (int i = 0; i < E; ++i) {
			scanf("%d%d", &a, &b);
			G[a].push_back(b);
			G[b].push_back(a);
		}
		solve();
    }
    return 0;
}

例:hdu4751

题意:一堆人,每个人单方面认识一些人,希望把这些人分成两堆,使得每一堆的人都相互认识。

题解:把所有不互相认识的人建边,如果是二分图,则可以。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;

const int MAX_V = 105;
bool knows[MAX_V][MAX_V];

vector<int> G[MAX_V];
int V;
int color[MAX_V];

bool dfs(int v, int c)
{
	color[v] = c;
	for (unsigned i = 0; i < G[v].size(); ++i) {
		if (color[G[v][i]] == c) return false;
		if (color[G[v][i]] == 0 && !dfs(G[v][i], -c)) return false;
	}
	return true;
}

void solve()
{
	for (int i = 1; i <= V; ++i) {
		if (color[i] == 0) {
			if (!dfs(i, 1)) {
				puts("NO");
				return ;
			}
		}
	}
	puts("YES");
}

int main()
{
    while (~scanf("%d", &V)) {

        memset(knows, false, sizeof knows);
        for (int i = 0; i <= V; ++i) G[i].clear();
		memset(color, 0, sizeof color);

        int a;
        for (int i = 1; i <= V; ++i) {
            while (~scanf("%d", &a) && a)
                knows[i][a] = true;
        }

        for (int i = 1; i <= V; ++i) {
            for (int j = i + 1; j <= V; ++j) {
                if (!knows[i][j] || !knows[j][i]) {
                    G[i].push_back(j);
                    G[j].push_back(i);
                }
            }
        }

        solve();
    }
    return 0;
}
时间: 2024-08-07 17:02:33

二分图判断(交叉染色)的相关文章

交叉染色法判断二分图

题目链接:传送门 题目大意:给你一副无向联通图,判断是不是二分图 题目思路:交叉染色法 下面着重介绍下交叉染色法的定义与原理 首先任意取出一个顶点进行染色,和该节点相邻的点有三种情况: 1.未染色    那么继续染色此节点(染色为另一种颜色) 2.已染色但和当前节点颜色不同      跳过该点 3.已染色并且和当前节点颜色相同       返回失败(该图不是二分图) 下面在拓展两个概念: (1) 如果一个双连通分量内的某些顶点在一个奇圈中(即双连通分量含有奇圈),那么这个双连通分量的其他顶点也在

UVA - 10004 Bicoloring(判断二分图——交叉染色法 / 带权并查集)

d.给定一个图,判断是不是二分图. s.可以交叉染色,就是二分图:否则,不是. 另外,此题中的图是强连通图,即任意两点可达,从而dfs方法从一个点出发就能遍历整个图了. 如果不能保证从一个点出发可以遍历整个图,那么编程要注意了,应该从每个点出发遍历一次. s2.带权并查集来判断,略复杂.先略过.先上个博客:http://blog.csdn.net/zsc09_leaf/article/details/6727622 c.邻接矩阵,bfs #include<iostream> #include&

poj2942 双联通分量+交叉染色法判断二分图

Knights of the Round Table Time Limit: 7000MS   Memory Limit: 65536K Total Submissions: 11805   Accepted: 3870 Description Being a knight is a very attractive career: searching for the Holy Grail, saving damsels in distress, and drinking with the oth

hdu 4751 2013南京赛区网络赛 二分图判断 **

和以前做过的一个二分图颇为相似,以前的是互相不认识的放在一组,这个是互相认识的,本质上是相同的 是 hdu 2444 1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 #include<queue> 7 #include<map> 8 using namespace st

hdu 2444 二分图判断与最大匹配

题意:有n个学生,有m对人是认识的,每一对认识的人能分到一间房,问能否把n个学生分成两部分,每部分内的学生互不认识,而两部分之间的学生认识.如果可以分成两部分,就算出房间最多需要多少间,否则就输出No. 首先判断是否为二分图,然后判断最大匹配 Sample Input 4 4 1 2 1 3 1 4 2 3 6 5 1 2 1 3 1 4 2 5 3 6Sample Output No 3 1 #include<iostream> 2 #include<string.h> 3 #i

HDU Catch (二分图判断奇环+并查集判断联通)

Problem Description A thief is running away!We can consider the city where he locates as an undirected graph in which nodes stand for crosses and edges stand for streets. The crosses are labeled from 0 to N–1. The tricky thief starts his escaping fro

二分图判定+点染色 BestCoder Round #48 ($) 1002 wyh2000 and pupil

题目传送门 1 /* 2 二分图判定+点染色:因为有很多联通块,要对所有点二分图匹配,若不能,存在点是无法分配的,no 3 每一次二分图匹配时,将点多的集合加大最后第一个集合去 4 注意:n <= 1,no,两个集合都至少有一人:ans == n,扔一个给另一个集合 5 */ 6 #include <cstdio> 7 #include <algorithm> 8 #include <cstring> 9 #include <cmath> 10 #in

hdu 2444 The Accomodation of Students 【二分图判断+求最大匹配】

题目链接:http://acm.acmcoder.com/showproblem.php?pid=2444 题意:判断所有人是否分为两个集合,每个集合里的人互不相识. 思路:先判断是否为二分图,是的话求最大匹配,否则输出"No". 代码: #include <stdio.h> #include <ctime> #include <math.h> #include <limits.h> #include <complex> #i

二分图判定--黑白染色

首先,二分图又叫二部图,特点是所有点分成两半,每一半内的点之间没有边相连,只有两半之间会有边相连,图内无奇环,当然,单点图或者有单点的图也属于二分图,因此最主要的区分就是图内无奇环了.对于一个图,是否是二分图,常用的方法是黑白染色,由于给定图常常不完全连通,所以只要对于每一个还未标记过的点,从它开始DFS按照黑白相间的方法标记颜色(0/1),每次DFS操作就是将这一连通块内按黑白分成两半,若途中遇到需要然成某种颜色但已经标记为另一种颜色时,则表明出现了奇环,不能构成二分图.而要注意,每次DFS只