二分图的定义及判断

二分图又称作二部图,是图论中的一种特殊模型。 设G=(V,E)是一个无向图,如果顶点V可分割为两个互不相交的子集(A,B),并且图中的每条边(i,j)所关联的两个顶点i和j分别属于这两个不同的顶点集(i in A, j in B),则称图G为一个二分图。

二分图的另一种等价的说法是,可以把每个节点着以黑色和白色之一,使得每条边的两个端点颜色不同.不难发现,非连通的图是二分图当且仅当每个连通分量都是二分图,因此我们只考虑无向连通图。


     

上图就是一个二分图

 

 

上图不是个二分图

 

那么我们如何去判断一个图是否是二分图呢?

这里我们采取的是二分图染色法:用两种颜色,对所有顶点逐个染色,且相邻顶点染不同的颜色,如果发现相邻顶点染了同一种颜色,就认为此图不为二分图。 当所有顶点都被染色,且没有发现同色的相邻顶点,就退出

 

第一种写法:DFS

 1 #include <stdio.h>
 2 #include <algorithm>
 3 #include <iostream>
 4 #include <stdbool.h>
 5 #include <stdlib.h>
 6 #include <string>
 7 #include <string.h>
 8 #include <math.h>
 9 #include <vector>
10 #include <queue>
11 #include <stack>
12 #include <set>
13 #include <map>
14 
15 #define INF 0x3f3f3f3f
16 #define LL long long
17 #define MAXN 1000010
18 using namespace std;
19 
20 vector<int> graph[MAXN];
21 int color[MAXN];
22 int vis[MAXN];
23 
24 bool DFS(int u)
25 {
26     vis[u] = 1;
27     int len = graph[u].size();
28     for (int j=0;j<len;j++)
29     {
30         int v = graph[u][j];
31         if (vis[v] == 0)  //如果没有染色
32         {
33             color[v] = color[u]^1;
34             if (!DFS(v))
35                 return false;
36         }
37         else if (color[u]==color[v]) //如果已经染色,但是相连的两点颜色相同
38             return false;
39     }
40     return true;
41 }
42 
43 int main()
44 {
45     int T;
46     scanf("%d",&T);
47     while (T--)
48     {
49         int n,m;
50         scanf("%d%d",&n,&m);
51         memset(graph,0, sizeof(graph));
52         for (int i=1;i<=m;i++)
53         {
54             int a,b;
55             scanf("%d%d",&a,&b);
56             graph[a].push_back(b);
57             graph[b].push_back(a);
58         }
59         memset(color,0, sizeof(color));
60         memset(vis,0, sizeof(vis));
61         int flag = true;
62         for (int i=1;i<=n;i++)
63         {
64             if (vis[i] == 0)
65             {
66                 if (!DFS(i))
67                 {
68                     flag = false;
69                     break;
70                 }
71             }
72         }
73         if (flag)
74             printf("Yes\n"); // 是二分图
75         else
76             printf("No\n");
77     }
78 }

 

第二种方法:BFS

 

 1 #include <stdio.h>
 2 #include <algorithm>
 3 #include <iostream>
 4 #include <stdbool.h>
 5 #include <stdlib.h>
 6 #include <string>
 7 #include <string.h>
 8 #include <math.h>
 9 #include <vector>
10 #include <queue>
11 #include <stack>
12 #include <set>
13 #include <map>
14 
15 #define INF 0x3f3f3f3f
16 #define LL long long
17 #define MAXN 100
18 using namespace std;
19 
20 vector<int> graph[MAXN];
21 int color[MAXN];
22 
23 
24 bool BFS(int u)
25 {
26     queue<int> que;
27     que.push(u);
28     color[u] = 1;
29     while (!que.empty())
30     {
31         int x = que.front();
32         que.pop();
33         for (int i=0;i<graph[x].size();i++)
34         {
35             int y = graph[x][i];
36             if (color[y] == 0)
37             {
38                 color[y] = color[x]^1;
39                 que.push(y);
40             }
41             else
42             {
43                 if (color[x] == color[y])
44                     return false;
45             }
46         }
47     }
48     return true;
49 }
50 
51 int main()
52 {
53     int n,m;
54     cin >> n >> m;
55     for (int i=1;i<=m;i++)
56     {
57         int x,y;
58         cin >> x >> y;
59         graph[x].push_back(y);
60         graph[y].push_back(x);
61     }
62     memset(color,0, sizeof(color));
63     //cout << BFS(1) << endl;
64     if (BFS(1))
65         cout << "YES" << endl;
66     else
67         cout << "NO" << endl;
68     return 0;
69 }

 

posted @ 2019-08-02 12:00  _Ackerman  阅读(1758)  评论(0编辑  收藏  举报