1. 程式人生 > >HiHo1121 : 二分圖一?二分圖判定(模板題)

HiHo1121 : 二分圖一?二分圖判定(模板題)

性別 不同 nbsp break 不同的 時也 ttl fence 個人

描述

大家好,我是小Hi和小Ho的小夥伴Nettle,從這個星期開始由我來完成我們的Weekly。

新年回家,又到了一年一度大齡剩男剩女的相親時間。Nettle去姑姑家玩的時候看到了一張姑姑寫的相親情況表,上面都是姑姑介紹相親的剩男剩女們。每行有2個名字,表示這兩個人有一場相親。由於姑姑年齡比較大了記性不是太好,加上相親的人很多,所以姑姑一時也想不起來其中有些人的性別。因此她拜托我檢查一下相親表裏面有沒有錯誤的記錄,即是否把兩個同性安排了相親。

OK,讓我們愉快的暴力搜索吧!

才怪咧。

對於拿到的相親情況表,我們不妨將其轉化成一個圖。將每一個人作為一個點(編號1..N),若兩個人之間有一場相親,則在對應的點之間連接一條無向邊。(如下圖)

因為相親總是在男女之間進行的,所以每一條邊的兩邊對應的人總是不同性別。假設表示男性的節點染成白色,女性的節點染色黑色。對於得到的無向圖來說,即每一條邊的兩端一定是一白一黑。如果存在一條邊兩端同為白色或者黑色,則表示這一條邊所表示的記錄有誤。

由於我們並不知道每個人的性別,我們的問題就轉化為判定是否存在一個合理的染色方案,使得我們所建立的無向圖滿足每一條邊兩端的頂點顏色都不相同

那麽,我們不妨將所有的點初始為未染色的狀態。隨機選擇一個點,將其染成白色。再以它為起點,將所有相鄰的點染成黑色。再以這些黑色的點為起點,將所有與其相鄰未染色的點染成白色。不斷重復直到整個圖都染色完成。(如下圖)

在染色的過程中,我們應該怎樣發現錯誤的記錄呢?相信你一定發現了吧。對於一個已經染色的點,如果存在一個與它相鄰的已染色點和它的顏色相同,那麽就一定存在一條錯誤的記錄。(如上圖的4,5節點)

到此我們就得到了整個圖的算法:

  1. 選取一個未染色的點u進行染色

  2. 遍歷u的相鄰節點v:若v未染色,則染色成與u不同的顏色,並對v重復第2步;若v已經染色,如果 u和v顏色相同,判定不可行退出遍歷。

  3. 若所有節點均已染色,則判定可行。

接下來就動手寫寫吧!

輸入

第1行:1個正整數T(1≤T≤10)

接下來T組數據,每組數據按照以下格式給出:

第1行:2個正整數N,M(1≤N≤10,000,1≤M≤40,000)

第2..M+1行:每行兩個整數u,v表示u和v之間有一條邊

輸出

第1..T行:第i行表示第i組數據是否有誤。如果是正確的數據輸出”Correct”,否則輸出”Wrong”

樣例輸入

2
5 5
1 2
1 3
3 4
5 2
1 5
5 5
1 2
1 3
3 4
5 2
3 5

樣例輸出

Wrong
Correct

Solve:

二分圖判斷模板題

Code:

技術分享
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 int t;
 4 int n , m;
 5 static const int MAXN = 1e4 + 10;
 6 vector <int> data[MAXN];
 7 bool flag;
 8 int vis[MAXN];
 9 bool Dfs(int x , int co)
10 {
11     vis[x] = co;
12     for(auto v: data[x])
13     {
14        if(vis[v] == co)
15             return 0;
16        if(vis[v] == -1 && !Dfs(v , !co))
17             return 0;
18     }
19     return 1;
20 
21 }
22 int main()
23 {
24     scanf("%d" , &t);
25     while(t--)
26     {
27         flag = 1;
28         scanf("%d%d" , &n , &m);
29         for(int i = 0 ; i <= n ; ++i)
30             data[i].clear() , vis[i] = -1;
31         for(int i = 1 ; i <= m ; ++i)
32         {
33             int x , y;
34             scanf("%d%d" , &x , &y);
35             data[x].push_back(y);
36             data[y].push_back(x);
37         }
38         for(int i = 0 ; i < n ; ++i)
39         {
40             if(vis[i] == -1)
41             {
42                 if(!Dfs(i , 0))
43                 {
44                     flag = false;
45                     break;
46                 }
47             }
48         }
49 
50         if(flag)
51             puts("Correct");
52         else
53             puts("Wrong");
54     }
55 }
View Code

HiHo1121 : 二分圖一?二分圖判定(模板題)