平均每天銷售 1000 輛,超越特斯拉,五菱巨集光 MINIEV 今年上半年銷量達 182767 輛
阿新 • • 發佈:2021-07-25
二分圖:在一個圖中,如果圖中的點可以被分為兩個部分,兩部分之間有若干條邊相連,且每個部分的點之間無邊相連,則該圖是一個二分圖。由此可以很容易知道,二分圖絕對是一個無環圖。
如上圖,圖一是一個二分圖,但從外表並不明顯,可以轉換成圖二的樣式。圖三是這個二分圖的一個匹配(紅線部分),圖四則是它的最大匹配,也是完美匹配。
#include <stdio.h> #include <vector> #include <string.h> using namespace std; const int N = 205; vector<int>G[N]; int n,m; int vis[N],pre[N]; //標記 存男朋友 int c[N]; //顏色 //用染色法判斷這個圖是否是二分圖 bool Dfs(int u,int colour){ c[u] = colour; for(int i = 0;i < G[u].size();i++){ int v = G[u][i]; if(c[v] == 0 && Dfs(v,3-colour)){ return true; }else if(c[v] != 3-colour) { printf("No\n"); return true; } } return false; } //用匈牙利演算法求出最大匹配數 bool dfs(int u){ for(int i = 0;i <G[u].size();i++){ int v = G[u][i]; if(!vis[v]){ vis[v] = 1; if(!pre[v] || dfs(pre[v])){//如果前一個可以移動也行 pre[v] = u;//記錄前一個 return true; } } } return false; } void solve(){ for(int i = 1;i <= n;i++){ //染色 if(c[i] == 0 && Dfs(i,1)){ return; } } int ans = 0; for(int i = 1;i <= n;i++){ //匈牙利 memset(vis,0,sizeof vis); if(dfs(i)) ans++; } printf("%d\n",ans); } void init(){ for(int i = 0;i < N;i++){ G[i].clear(); } memset(pre,0,sizeof pre); memset(c,0,sizeof c); } int main(){ while(~scanf("%d%d",&n,&m)){ init(); while(m--){ int x,y; scanf("%d%d",&x,&y); G[x].push_back(y); } solve(); } return 0; }
最大匹配數:最大匹配的匹配邊的數目
最小點覆蓋數:選取最少的點,使任意一條邊至少有一個端點被選擇
最大獨立數:選取最多的點,使任意所選兩點均不相連
最小路徑覆蓋數:對於一個 DAG(有向無環圖),選取最少條路徑,使得每個頂點屬於且僅屬於一條路徑。路徑長可以為 0(即單個點)。
定理1:最大匹配數 = 最小點覆蓋數(這是 Konig 定理)
定理2:最大匹配數 = 最大獨立數
定理3:最小路徑覆蓋數 = 頂點數 - 最大匹配數