1. 程式人生 > 其它 >染色法判定二分圖

染色法判定二分圖

接下來的內容,是關於基礎圖論的最後一節:二分圖的相關問題;

 

我們先簡單介紹一下二分圖,二分圖不一定是一個連通塊,可能是多個連通塊組成,然後我們把所有的點分別劃分為兩個部分,一個在左邊的點集中,另一個在右邊的點集中,所有的邊只存在於兩個點集之間,而在點集內部是不會存在連邊的,這樣的圖我們就叫作二分圖;

 

這裡我們要先介紹一下如何判定一個圖是不是二分圖,我們是通過染色法來確定的,我們給一個未染色的點染上白色,記為1,然後因為連邊存在於點集之間,我們給與這個點相連的點都放在另一邊並染成黑色,記為2,所以我們知道如果一個連通塊中的一個點已經被染色,我們就可以去把所有的點都給染色,所以遍歷一個連通塊,我們在這裡使用dfs的思路,染色法什麼時候可以判斷出這不是個二分圖呢,就是我在遍歷當前點的下一個點的時候發現下一個點已經被染色且與當前點的顏色一致,說明邊出現在了點集內部,這不是一個二分圖!

 

程式碼:

#include<bits/stdc++.h>
#define maxn 100010
#define maxm 200010

using namespace std;
int h[maxn],e[maxm],ne[maxm],idx;
int n,m;
int color[maxn];

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

bool dfs(int t,int c){
color[t] = c;
for(int i = h[t];i!=-1;i = ne[i])
{
int j = e[i];


if(!color[j]){
if(!dfs(j,3-c)) return false;
}
else if(color[j] == c) return false;
}
return true;
}

int main()
{
memset(h, -1, sizeof h);
cin >> n >> m;
while (m -- ){
int a,b;
cin >> a >> b;
add(a, b); add(b, a);


}
bool flag = false;
for(int i = 1;i<=n;i++){
if(!color[i]){
if(!dfs(i , 1)) flag = true;
}
}
if(flag) cout << "No" << '\n';
else cout << "Yes" << '\n';
return 0;
}

 

分析:這裡給dfs返回型別確定為bool型別已經不是第一次了,我們在拓撲排序的時候判斷有沒有環的時候就已經用到過了;

·這裡利用3-c在1,2之間切換有點意思!