圖論——染色法判定二分圖


  首先明確概念:

  二分圖:設G=(V,E)是一個無向圖,如果頂點V可分割為兩個互不相交的子集(A,B),並且圖中的每條邊(i,j)所關聯的兩個頂點i和j分別屬於這兩個不同的頂點集(i in A,j in B),則稱圖G為一個二分圖。

  奇數環:一個圖中邊數為奇數的環。

  染色法原理:

  首先任意取出一個頂點進行染色,和該節點相鄰的點有三種情況:

  1.如果未染色,那么繼續染色此節點(染為另一種顏色)

  2.如果已染色但和當前節點顏色不同,則跳過該點

  3.如果已染色並且和當前節點顏色相同,返回失敗(該圖不是二分圖)

  明確二分圖、奇數環、染色法之間的關系:

  如果一個圖中存在奇數環,那么這個圖一定不是二分圖;這一點顯然成立。

  如果一個圖中不存在奇數環,那么這個圖一定是二分圖:

  證明:用染色法。從某個點開始逐層交叉染色,在染色過程中:

    若發現有某條邊的兩個端點着色相同,則必定存在奇數環①,與題意相矛盾。

    若沒有發現,則根據染色法原理,每一條邊的兩端着色必然不同,那么根據二分圖的定義,就可知這個圖是一個二分圖。

    ①的證明:

      不妨設這條邊的兩個端點着色都為1,且這兩點必然是由同一個源點擴展而來。那么根據染色法原理,因為這兩個點的着色相同,那么從源點到這兩個點所經過的邊數(假設分別為x和y)的奇偶性必然相同,那么這個環的總邊數為x+y+1,由數學知識得這個數必然是奇數。 

    證畢!

  模板題鏈接:染色法判定二分圖

  代碼如下:

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
using namespace std;
const int N = 100010, M = 200010;
struct Edge{
    int to,next;
}edge[M];int cnt;
int n,m;
int h[N],color[N];

void add_edge(int u,int v)
{
    edge[++cnt].to=v;
    edge[cnt].next=h[u];
    h[u]=cnt;
}

bool dfs(int u,int c)
{
    color[u]=c;
    for(int i=h[u]; ~ i;i=edge[i].next)
    {
        int to=edge[i].to;
        if(color[to]==c)
        {
            return false;
        }
        else if(!color[to]&&!dfs(to,3-c))return false;
    }
    return true;
}

int main()
{
    scanf("%d%d",&n,&m);
    memset(h,-1,sizeof h);
    for(int i=1;i<=m;i++)
    {
        int a,b;scanf("%d%d",&a,&b);
        add_edge(a,b);add_edge(b,a);
    }
    bool flag=true;
    for(int i=1;i<=n;i++)
    {
        if(!color[i])
        {
            if(!dfs(i,1))
            {
                flag=false;
                break;
            }
        }
    }
    if(flag)printf("Yes\n");
    else printf("No\n");
}

 


免責聲明!

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



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