从二分图最大匹配到二分图最优匹配
-
二分图最大匹配
-
没啥说得,直接上代码。
-
int vispipei[maxn],match[maxn]; int dfspipei(int now) { for(int i=1;i<=nn;i++) if(dis[now][i]) { int nex=i; if(!vispipei[nex]) { vispipei[nex]=1; if(match[nex]==0 || dfspipei(match[nex])) { match[nex]=now; return true; } } } return false; } int solve() { for(int i=1;i<=nn;i++) match[i]=0; int cnt=0; for(int i=1;i<=nn;i++) { for(int j=1;j<=nn;j++) vispipei[j]=0; if(!dfspipei(i)) cnt++; } return cnt; }
-
使用的时候千万要注意把return写够!以及match和vis数组的清空!
-
应用
- 最小点覆盖=最大匹配
- 最小路径覆盖= ∣ V ∣ |V| ∣V∣-最大匹配
- 最大独立集= ∣ V ∣ |V| ∣V∣-最大匹配。最大独立集S 与 最小覆盖集T 互补
-
拓展
- 存在一种复杂度为 o ( n ∗ e ) o(\sqrt{n}*e) o(n∗e)的二分图最大匹配算法,名字为HK,其实本质上就是网络流了
- 我记得在我高二的时候听一个课,课上说了用网络流跑最大匹配就是这个复杂度。
- 如果非要写HK,HK的具体步骤为:
- BFS
- 首先把二分图染成黑色的点加到队列里。
- 对于每一个队列里的点
u
u
u,与它相连的点
v
v
v,如果
v
v
v没被访问过,首先深度设为
d
e
p
[
u
]
+
1
dep[u]+1
dep[u]+1
- 如果没被匹配,则找到了一条增广路,对 v v v就什么都不做最后 r e t u r n t r u e return\ true return true
- 否则将与 v v v匹配的点,加到队列里。
- DFS
- 与匈牙利的类似,只不过要求 d e p [ v ] dep[v] dep[v] 必须是 d e p [ u ] + 1 dep[u]+1 dep[u]+1
- BFS
-
-
二分图最优匹配
-
也没啥说得,直接上代码。
-
int nn; int wx[maxn],wy[maxn],weight[maxn][maxn],st[maxn]; int bel[maxn],visx[maxn],visy[maxn]; int dfs(int u) { visx[u]=1; for(int v=1;v<=nn;v++) { if(visy[v]) continue; int t=wx[u]+wy[v]-weight[u][v]; if(!t) { visy[v]=1; if(bel[v]==-1||dfs(bel[v])) { bel[v]=u; return 1; } } else if(st[v]>t) st[v]=t; } return 0; } int km() { for(int i=1;i<=nn;i++) wx[i]=-inf,bel[i]=-1,wy[i]=0; for(int i=1;i<=nn;i++) { for(int j=1;j<=nn;j++) { wx[i]=max(wx[i],weight[i][j]); } } for(int i=1;i<=nn;i++) { for(int j=1;j<=nn;j++) { st[j]=inf; } while(1) { for(int j=1;j<=nn;j++) visx[j]=visy[j]=0; if(dfs(i)) break; int ret=inf; for(int j=1;j<=nn;j++) if(!visy[j]&&ret>st[j]) ret=st[j]; for(int j=1;j<=nn;j++) if(visx[j]) wx[j]-=ret; for(int j=1;j<=nn;j++) { if(visy[j]) wy[j]+=ret; else st[j]-=ret; } } } int ans=0; for(int i=1;i<=nn;i++) if(~bel[i]) ans+=weight[bel[i]][i]; return ans; } int solve() { for(int i=1;i<=nn;i++) { for(int j=1;j<=nn;j++) { weight[i][j]=-inf; } } getweight(); return km(); }
-
两个模板如果多次使用都要注意清空!
-
二分图有最优匹配首先得有最大匹配。
-