我國“天問一號”環繞器成功實施第五次近火制動,進入遙感使命軌道
阿新 • • 發佈:2021-11-08
二分圖
定義
二分圖,又稱二部圖,英文名叫 Bipartite graph。
二分圖是什麼?節點由兩個集合組成,且兩個集合內部沒有邊的圖。
換言之,存在一種方案,將節點劃分成滿足以上性質的兩個集合。
二分圖的性質:二分圖一定不存在長度為奇數的環
染色法判定是否為二分圖
思路分析:我們可以對每個點進行DFS並進行染色,如果存在一條邊的兩點顏色相同則說明不是二分圖。
程式碼示例:
//#pragma comment(linker, "/STACK:10240000000000,10240000000000") //#pragma GCC optimize(2) #include <bits/stdc++.h> using namespace std; #define For(i,a,b) for (int i=(a);i<=(b);++i) #define Fod(i,b,a) for (int i=(b);i>=(a);--i) #define mls multiset #define lb lower_bound #define ub upper_bound #define pb push_back #define pob pop_back #define itt iterator #define endl '\n' #define IOS ios::sync_with_stdio(0); cin.tie(0); #define lowbit(x) x & (-x) #define clr(x) memset(x, 0, sizeof(x)); #define fi first #define se second typedef vector<int> vii; typedef vector<long long> vll; typedef long long ll; typedef unsigned long long ull; typedef pair<int, int> pii; typedef pair<ll, ll> pll; const int MAXN = 0x7fffffff; const int MOD = 1000000007; const ll MOD1 = 212370440130137957ll; const int N = 1e5 + 5; int h[N], e[2 * N], ne[2 * N], idx; int color[N]; int n, m; void add(int a, int b) { e[idx] = b, ne[idx] = h[a], h[a] = idx++; } bool dfs(int u, int c) { color[u] = c; for(int i = h[u]; i != -1; i = ne[i]) //對點u的每條出邊進行染色 { int j = e[i]; if(!color[j]) //如果還沒有染色 { if(!dfs(j, 3 - c)) return false; //如果染色失敗 } else if(color[j] == c) return false; //如果兩點顏色相同 } return true; } int main () { //IOS; cin >> n >> m; memset(h, -1, sizeof h); for(int i = 1; i <= m; i ++) { int a, b; cin >> a >> b; add(a, b); add(b, a); } bool flag = true; for(int i = 1; i <= n; i ++) if(!color[i]) if(!dfs(i, 1)) //dfs(i, c)表示對i進行dfs染色後是否成功 { flag = false; break; } if(flag) puts("Yes"); else puts("No"); return 0; }
二分圖最大匹配----匈牙利演算法
我們先將點歸為兩個集合,分別記為1和2
由於要找到最大匹配,我們只需對1進行遍歷向2匹配即可,不用對2再進行一遍同樣操作。對於每一個點,我們先遍歷他的所有出邊,隨後只要找到一個能匹配的就進行匹配,並用陣列記錄下來,但如果出邊的終點已經有匹配了,則就再去尋找出邊終點匹配的點(已用陣列記錄)是否有其他可匹配的點
程式碼示例:
//#pragma comment(linker, "/STACK:10240000000000,10240000000000") //#pragma GCC optimize(2) #include <bits/stdc++.h> using namespace std; #define For(i,a,b) for (int i=(a);i<=(b);++i) #define Fod(i,b,a) for (int i=(b);i>=(a);--i) #define mls multiset #define lb lower_bound #define ub upper_bound #define pb push_back #define pob pop_back #define itt iterator #define endl '\n' #define IOS ios::sync_with_stdio(0); cin.tie(0); #define lowbit(x) x & (-x) #define clr(x) memset(x, 0, sizeof(x)); #define fi first #define se second typedef vector<int> vii; typedef vector<long long> vll; typedef long long ll; typedef unsigned long long ull; typedef pair<int, int> pii; typedef pair<ll, ll> pll; const int MAXN = 0x7fffffff; const int MOD = 1000000007; const ll MOD1 = 212370440130137957ll; const int N = 505; const int M = 1e5 + 5; int n1, n2, m; int h[N], ne[M], e[M], idx; int match[N]; bool st[N]; void add(int a, int b) { e[idx] = b, ne[idx] = h[a], h[a] = idx ++; } bool find(int x) { for(int i = h[x]; ~i; i = ne[i]) { int j = e[i]; if(st[j]) continue;//j這一輪已經匹配了 st[j] = true; if(match[j] == 0 || find(match[j])) //match[j]存的是當前j的匹配物件 { match[j] = x; //進行匹配 return true; } } return false; } int main () { //IOS; cin >> n1 >> n2 >> m; memset(h, -1, sizeof h); for(int i = 1; i <= m; i ++) { int a, b; cin >> a >> b; add(a, b); } int res = 0; for(int i = 1; i <= n1; i ++) { memset(st, false, sizeof st); //每次都要初始化st,因為每一輪遍歷都有可能推翻之前的匹配 if(find(i)) res ++; } cout << res << endl; return 0; }