題目鏈接:傳送門
題目大意:給你一副無向聯通圖,判斷是不是二分圖
題目思路:交叉染色法
下面着重介紹下交叉染色法的定義與原理
首先任意取出一個頂點進行染色,和該節點相鄰的點有三種情況:
1.未染色 那么繼續染色此節點(染色為另一種顏色)
2.已染色但和當前節點顏色不同 跳過該點
3.已染色並且和當前節點顏色相同 返回失敗(該圖不是二分圖)
下面在拓展兩個概念:
(1) 如果一個雙連通分量內的某些頂點在一個奇圈中(即雙連通分量含有奇圈),那么這個雙連通分量的其他頂點也在某個奇圈中;
第一個條件的證明:我們假設有一個奇圈,因為是點雙,沒有割點,必然有緊挨着的圈,假設這個是偶數圈,則,這個偶數圈必然能和原來的奇圈組成新的奇圈(因為:新的圈=(奇數圈-k)+(偶數圈-k)=奇數+偶數-偶數=奇數,k是共同邊上的點數
(2) 如果一個雙連通分量含有奇圈,則他必定不是一個二分圖。反過來也成立,這是一個充要條件。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstdlib> 4 #include <cmath> 5 #include <algorithm> 6 #include <cstring> 7 #include <stack> 8 #include <cctype> 9 #include <queue> 10 #include <string> 11 #include <vector> 12 #include <set> 13 #include <map> 14 #include <climits> 15 #define lson root<<1,l,mid 16 #define rson root<<1|1,mid+1,r 17 #define fi first 18 #define se second 19 #define ping(x,y) ((x-y)*(x-y)) 20 #define mst(x,y) memset(x,y,sizeof(x)) 21 #define mcp(x,y) memcpy(x,y,sizeof(y)) 22 #define Min(x,y) (x<y?x:y) 23 #define Max(x,y) (x>y?x:y) 24 using namespace std; 25 #define gamma 0.5772156649015328606065120 26 #define MOD 1000000007 27 #define inf 0x3f3f3f3f 28 #define N 5005 29 #define maxn 10005 30 typedef long long LL; 31 typedef pair<int,int> PII; 32 33 int pic[200][200]; 34 int vis[200],n,m; 35 36 inline void init(){ 37 mst(vis,-1); 38 mst(pic,0); 39 } 40 41 int dfs(int x,int c){ 42 if(vis[x]!=-1&&vis[x]==c)return 0; 43 vis[x]=c; 44 for(int i=0;i<n;++i){ 45 if(pic[x][i]){ 46 if(vis[i]==-1) 47 dfs(i,c^1); 48 else if(vis[i]==c)return 0; 49 } 50 } 51 return 1; 52 } 53 54 int main(){ 55 int i,j,group,Case=0,x,y; 56 while(scanf("%d",&n)!=EOF&&n){ 57 scanf("%d",&m); 58 init(); 59 if(n==0)break; 60 while(m--){ 61 scanf("%d%d",&x,&y); 62 pic[x][y]=pic[y][x]=1; 63 } 64 if(dfs(0,0))printf("BICOLORABLE.\n"); 65 else printf("NOT BICOLORABLE.\n"); 66 } 67 return 0; 68 }