二分圖判斷(交叉染色)


二分圖又稱二部圖。

二分圖是無向圖

設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;
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM