二分圖又稱二部圖。
二分圖是無向圖。
設G=(V,E)是一個無向圖。如頂點集V可分割為兩個互不相交的子集,並且圖中每條邊依附的兩個頂點都分屬兩個不同的子集。
例如這就是一個二分圖。 大概就是把頂點分成兩堆,每堆內部沒有邊。
無向圖G為二分圖的充分必要條件是,G至少有兩個頂點, 且其所有回路的長度均為偶數。
最大獨立點集:在二分圖中,求最少的點集,使得任意兩個點之間沒有直接邊連接。
最小點覆蓋:在二分圖中,求最少的點集,使得每一條邊至少都有端點在這個點集中。
二分圖判斷:二分圖染色。
給一個無向圖。要給圖上每個頂點染色,並且使任意相鄰的頂點染色不同。並且最多用兩種顏色。
如果可以進行二分圖染色,證明是一個二分圖。
如果可以染色,就是如上圖,把每一個顏色放入一個堆,就構成了二分圖。
模板:
#include <iostream> #include <cstdio> #include <cstring> #include <vector> using namespace std; const int MAX_V = 205; vector<int> G[MAX_V]; // 圖 int V; // 頂點數 int color[MAX_V]; // 頂點i的顏色 1 或 -1 // 把頂點染成1或-1 bool dfs(int v, int c) { color[v] = c; // 把頂點v染成顏色c for (int i = 0; i < G[v].size(); ++i) { if (color[G[v][i]] == c) return false; if (color[G[v][i]] == 0 && !dfs(G[v][i], -c)) return false; } return true; } void solve() { for (int i = 0; i < V; ++i) { if (color[i] == 0) { if (!dfs(i, 1)) { puts("No"); return ; } } } puts("Yes"); } int main() { int E; while (scanf("%d%d", &V, &E) == 2) { int a, b; for (int i = 0; i < V; ++i) G[i].clear(); memset(color, 0, sizeof color); for (int i = 0; i < E; ++i) { scanf("%d%d", &a, &b); G[a].push_back(b); G[b].push_back(a); } solve(); } return 0; }
例:hdu4751
題意:一堆人,每個人單方面認識一些人,希望把這些人分成兩堆,使得每一堆的人都相互認識。
題解:把所有不互相認識的人建邊,如果是二分圖,則可以。
#include <iostream> #include <cstdio> #include <cstring> #include <vector> using namespace std; const int MAX_V = 105; bool knows[MAX_V][MAX_V]; vector<int> G[MAX_V]; int V; int color[MAX_V]; bool dfs(int v, int c) { color[v] = c; for (unsigned i = 0; i < G[v].size(); ++i) { if (color[G[v][i]] == c) return false; if (color[G[v][i]] == 0 && !dfs(G[v][i], -c)) return false; } return true; } void solve() { for (int i = 1; i <= V; ++i) { if (color[i] == 0) { if (!dfs(i, 1)) { puts("NO"); return ; } } } puts("YES"); } int main() { while (~scanf("%d", &V)) { memset(knows, false, sizeof knows); for (int i = 0; i <= V; ++i) G[i].clear(); memset(color, 0, sizeof color); int a; for (int i = 1; i <= V; ++i) { while (~scanf("%d", &a) && a) knows[i][a] = true; } for (int i = 1; i <= V; ++i) { for (int j = i + 1; j <= V; ++j) { if (!knows[i][j] || !knows[j][i]) { G[i].push_back(j); G[j].push_back(i); } } } solve(); } return 0; }