1. 程式人生 > 實用技巧 >860. 染色法判定二分圖

860. 染色法判定二分圖

給定一個n個點m條邊的無向圖,圖中可能存在重邊和自環。

請你判斷這個圖是否是二分圖。

輸入格式

第一行包含兩個整數n和m。

接下來m行,每行包含兩個整數u和v,表示點u和點v之間存在一條邊。

輸出格式

如果給定圖是二分圖,則輸出“Yes”,否則輸出“No”。

資料範圍

1n,m1051≤n,m≤105

輸入樣例:

4 4
1 3
1 4
2 3
2 4

輸出樣例:

Yes


染色思路
二分圖:判斷一個圖是否二分圖主要看這個圖有沒有奇數環,有奇數環的就不是二分圖。
①:給定任意一個點開始染色,假設第一個點染色1,那麼這個點的所有連通點都染色2,相對應的,染色2的點的所有連通點都染色為1
②:如果這個圖所有點都染色後不會發生矛盾,那麼該圖就是二分圖,否則就不是。

如圖所示,這個圖染色結束後並無衝突 所以是二分圖:

這個圖染色以後發生衝突 不是二分圖:

程式碼詳情如下
#include<iostream>
#include<cstring>
#include<algorithm>

using namespace std;

const int N = 100010, M = 200010;   //無向邊所以M要*2

int n, m;
int h[N], e[M], ne[M], idx;
int color[N];

void add(int a, int b)  //同樣用鄰接矩陣來儲存
{
    e[idx] = b, ne[idx] = h[a], h[a] = idx ++;
}

bool dfs(int u, int c) //u是當前節點,c是染色點 { color[u] = c; //首先給當前節點染c for(int i = h[u]; i != -1; i = ne[i]) //從前到後遍歷節點 { int j = e[i]; //用j儲存當前節點號數 if(!color[j]) //如果當前節點沒有染色 { //把當前節點所連通的點都深搜, //然後染上3-c(如果當前是1,連通點應該染3-1=2;如果是2,連通點染3-2=1) if
(!dfs(j, 3 - c)) return false; } //如果當前節點染色了並且和c相同,說明有奇數環 else if (color[j] == c) return false; } return true; } int main() { scanf("%d%d", &n,&m); memset(h, -1, sizeof h); while(m -- ) { int a,b; scanf("%d%d", &a, &b); add(a,b),add(b,a); } bool flag = true; //定義一個flag來判斷當前圖是否有矛盾 for(int i = 1; i <= n; i ++) //遍歷全部節點 { if(!color[i]) //如果沒有染色我們就對它深搜染色 { if(!dfs(i,1)) //如果深搜發現有奇數環,那說明圖有矛盾,不是二分圖 { flag = false; break; } } } if(flag) puts("Yes"); else puts("No"); return 0; }