程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> hihoCoder - 1121 - 二分圖判定

hihoCoder - 1121 - 二分圖判定

編輯:C++入門知識

hihoCoder - 1121 - 二分圖判定


 

 

#1121 : 二分圖一•二分圖判定

時間限制:10000ms 單點時限:1000ms 內存限制:256MB

描述

大家好,我是小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

     

     

     

    好久沒寫代碼,,繼續攢點模板!

     

    AC代碼:

     

    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    using namespace std;
    
    int T;
    int n, m;
    
    const int  maxn = 10005;
    vector G[maxn];
    
    bool vis[maxn];
    int f[maxn];
    
    int bfs(int i) {
    	queue que;
    	que.push(i);
    	vis[i] = true;
    	f[i] = 0;
    	while(!que.empty()) {
    		int e = que.front();
    		que.pop();
    		int d = G[e].size();
    //		cout << e << endl;
    		for(int i = 0; i < d; i ++) {
    			int t = G[e][i];
    //			cout << t <<  ;
    			if(vis[t]) {
    				if(f[t] == f[e]) return 1;
    			}
    			else {
    				vis[t] = true;
    				f[t] = f[e] == 0 ? 1 : 0;
    				que.push(t);
    			}
    		}
    //		cout << endl;
    	}
    	return 0;
    }
    
    int fun() {		//注意可能會有多個連通分量 
    	for(int i = 1; i <= n; i ++) {
    		if(!vis[i]) {
    			if(bfs(i) == 1) return 1;
    		}
    	}
    	return 0;
    }
    
    int main() {
    	scanf(%d, &T);
    	while(T --) {
    //		for(int i = 0; i < maxn; i ++) G[i].clear();
    		scanf(%d %d, &n, &m);
    		for(int i = 0; i < m; i ++) {
    			int u, v;
    			scanf(%d %d, &u, &v);
    			G[u].push_back(v);
    			G[v].push_back(u);
    		}
    		
    		memset(vis, false, sizeof(vis));
    		
    		if(fun() == 1) {
    			printf(Wrong
    );
    		}
    		else printf(Correct
    );
    //		for(int i = 1; i <= n; i ++) {
    //			cout << f[i] <<  ;
    //		}
    		for(int i = 1; i <= n; i ++) G[i].clear();
    	}
    	return 0;
    }


     

     

     

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved