染色法判断是否是二分图 hdu2444
用染色法判断二分图是这样进行的,随便选择一个点,
1.把它染成黑色,然后将它相邻的点染成白色,然后入队列
2.出队列,与这个点相邻的点染成相反的颜色
根据二分图的特性,相同集合内的点颜色是相同的,即
但是如果这个图不是二分图,那么就会这样
把与1相邻的点2,3染成白色,然后入队列,然后2出队列,要把与2相邻的点2,3染成黑色,但是都染过了,所以不用染色
但是3的颜色应该与2相反(如果是二分图的话),可是没有相反,所以就不是二分图
1 #include <stdio.h> 2 #include <queue> 3 #include <string.h> 4 using namespace std; 5 const int N = 300; 6 struct Edge 7 { 8 int v,next; 9 }g[N*N]; 10 int first[N*N]; 11 int color[N*N]; 12 int cy[N]; 13 bool vis[N]; 14 int e; 15 int n,m; 16 bool is_ ; 17 void addEdge(int a, int b) 18 { 19 g[e].v = b; 20 g[e].next =first[a]; 21 first[a] = e++; 22 } 23 bool bfs(int cur)//染色法,判断是否是二分图 24 {//时间复杂度 邻居矩阵O(n*n) 邻接表 O(n+e) 25 queue<int> q; 26 q.push(cur); 27 color[cur] = 1; 28 while(!q.empty()) 29 { 30 cur = q.front();q.pop(); 31 for(int i=first[cur]; i!=-1; i=g[i].next) 32 { 33 int v = g[i].v; 34 if(color[v] == -1) 35 { 36 color[v] = 1 - color[cur]; 37 q.push(v); 38 } 39 40 if(color[v] == color[cur]) 41 return false; 42 } 43 } 44 return true; 45 } 46 void dfs_color(int cur) 47 { 48 for(int i=first[cur]; i!=-1; i=g[i].next) 49 { 50 int v = g[i].v; 51 if(color[v] == -1) 52 { 53 color[v] = 1 - color[cur]; 54 dfs_color(v); 55 } 56 else if(color[v] == color[cur]) 57 is_ = false; 58 59 } 60 61 } 62 bool dfs(int cur) 63 { 64 for(int i=first[cur]; i!=-1; i=g[i].next) 65 { 66 int v = g[i].v; 67 if(!vis[v]) 68 { 69 vis[v] = true; 70 if(cy[v]==-1 || dfs(cy[v])) 71 { 72 cy[v] = cur; 73 return true; 74 } 75 } 76 } 77 return false; 78 } 79 int Match() 80 { 81 int ans = 0; 82 memset(cy, -1, sizeof(cy)); 83 for(int i=1; i<=n; ++i) 84 { 85 memset(vis, 0, sizeof(vis)); 86 ans += dfs(i); 87 } 88 return ans; 89 } 90 int main() 91 { 92 freopen("in.txt","r",stdin); 93 int a,b,i; 94 while(scanf("%d%d",&n,&m)!=EOF) 95 { 96 memset(first, -1, sizeof(first)); 97 e = 0; 98 for(i=0; i<m; ++i) 99 { 100 scanf("%d%d",&a,&b); 101 addEdge(a,b); 102 addEdge(b,a); 103 } 104 is_ = true; 105 memset(color, -1, sizeof(color)); 106 for(i=1; i<=n; ++i) 107 { 108 if(color[i] == -1) 109 { 110 color[i] = 1; 111 dfs_color(i); 112 } 113 } 114 if(!is_) 115 puts("No"); 116 else 117 { 118 printf("%d\n",Match()/2);//没有把集合x,y分开,所以相当有2个最大匹配 119 } 120 } 121 }