染色法判定二分圖

染色法判定二分圖

二分圖概念:當且僅當圖中不含奇數環-環邊是奇數。

注意:相鄰點染的顏色不同,因爲圖中沒有奇數環所以染色過程是一定沒有矛盾的。

Example

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

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

輸入格式

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

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

輸出格式

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

數據範圍

1≤n,m≤1051≤n,m≤105

輸入樣例:

4 4
1 3
1 4
2 3
2 4

輸出樣例:

Yes
#include <iostream>
#include <algorithm>
#include <cstring>

using namespace std;

const int N = 100010, M = 200010;

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

//dfs一遍
bool dfs(int u, int c)
{
    //記錄當前點的顏色
    color[u] = c;
    
    //遍歷當前點零點
    for (int i = h[u]; i != -1; i = ne[i])
    {
        //記錄當前點編號
        int j = e[i];
        if (!color[j])//如果沒有染色,則染成另外一種顏色 3 - c
        {//3 - c: 把1變成2或者把2變成1
            if(!dfs(j, 3 - c)) return false;
        }
        //當前j已經染了顏色,如果和當前顏色不同則矛盾
        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;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章