一、二分图
1、最大匹配数 = 最大流 = 最小割 = 最小点集覆盖 = 总点数 - 最大独立集
2、KM算法(最佳完美匹配)
1 int mat[MAXN][MAXN], slack[MAXN], Lx[MAXN], Ly[MAXN], left[MAXN]; 2 bool S[MAXN], T[MAXN]; 3 4 bool dfs(int i) 5 { 6 S[i] = true; 7 for(int j = 1; j <= n; ++j) if(!T[j]) { 8 int t = Lx[i] + Ly[j] - mat[i][j]; 9 if(t == 0){ 10 T[j] = true; 11 if(!left[j] || dfs(left[j])){ 12 left[j] = i; 13 return true; 14 } 15 } 16 else slack[j] = min(slack[j],t); 17 } 18 return false; 19 } 20 21 void update() 22 { 23 int a = INF; 24 for(int i = 1; i <= n; ++i) if(!T[i]) 25 a = min(slack[i],a); 26 for(int i = 1; i <= n; ++i){ 27 if(S[i]) Lx[i] -= a; 28 if(T[i]) Ly[i] += a; else slack[i] -= a; 29 } 30 } 31 32 int KM() 33 { 34 for(int i = 1; i <= n; ++i){ 35 Lx[i] = Ly[i] = left[i] = 0; 36 for(int j = 1; j <= n; ++j) Lx[i] = max(Lx[i],mat[i][j]); 37 } 38 for(int i = 1; i <= n; ++i){ 39 for(int j = 1; j <= n; ++j) slack[j] = INF; 40 while(1){ 41 for(int j = 1; j <= n; ++j) S[j] = T[j] = 0; 42 if(dfs(i)) break; else update(); 43 } 44 } 45 int ans = 0; 46 for(int i = 1; i <=n; ++i) ans += Lx[i] +Ly[i]; 47 return ans; 48 }