6 3 3 1 1 1 2 1 3 2 1 2 3 3 1 0
3
匈牙利算法看起来很复杂,实际上通过dfs巧妙的得出结果。
补充定义和定理:
最大匹配数:最大匹配的匹配边的数目
最小点覆盖数:选取最少的点,使任意一条边至少有一个端点被选择
最大独立数:选取最多的点,使任意所选两点均不相连
最小路径覆盖数:对于一个 DAG(有向无环图),选取最少条路径,使得每个顶点属于且仅属于一条路径。路径长可以为 0(即单个点)。
定理1:最大匹配数 = 最小点覆盖数(这是 Konig 定理)
定理2:最大匹配数 = 最大独立数
定理3:最小路径覆盖数 = 顶点数 - 最大匹配数
#include <iostream> #include <stdio.h> #include <stdlib.h> #include<string.h> #include<algorithm> #include<math.h> #include<queue> using namespace std; typedef long long ll; const int N=555; bool tu[N][N]; int from[N];///记录右边的点如果配对好了它来自哪里 bool use[N];///记录右边的点是否已经完成了配对 int n,m;///m,n分别表示两边的各自数量,n是左边,m是右边 bool dfs(int x) { for(int i=1;i<=m;i++)///m是右边,所以这里上界是m if(!use[i]&&tu[x][i]) { use[i]=1; if(from[i]==-1||dfs(from[i])) { from[i]=x; return 1; } } return 0; } int hungary() { int tot=0; memset(from,-1,sizeof(from)); for(int i=1;i<=n;i++)///n是左边,所以这里上界是n { memset(use,0,sizeof(use)); if(dfs(i)) tot++; } return tot; } int main() { int k; while(cin>>k&&k) { memset(tu,0,sizeof(tu)); cin>n>>m; int a,b; while(k--) { cin>>a>>b; tu[a][b]=1; } printf("%d\n",hungary()); } return 0; }