模板——二分图匹配KM
具体方法就不介绍了,详见 https://blog.csdn.net/sixdaycoder/article/details/47720471
主要讲一些注意点:
1:不直接将未匹配的y减小是因为要保证lx[i]+ly[j]>=w[i][j],证明详见上述博客
2:因为多组数据,所有数组都记得清零
3:dfs中坑了我20多次MLE……记得visx,visy数组都要更新
4:这种做法仅限于每一个点都能被匹配的情况,若不能都匹配就要用网络流
5:只有在值相等时才能赋值visy
二分图匹配模板题:(值得思考)
1 #include<bits/stdc++.h> 2 using namespace std; 3 int V,n,m,e; 4 vector<int> v[1005]; 5 int vis[1005],match[1005]; 6 7 int init() 8 { 9 memset(match,-1,sizeof(match)); 10 scanf("%d%d%d%d",&V,&n,&m,&e); 11 for(int i=1;i<=e;i++) 12 { 13 int x,y; 14 scanf("%d%d",&x,&y); y+=n; 15 v[x].push_back(y); 16 } 17 } 18 19 int dfs(int u) 20 { 21 for(int i=0;i<(int)v[u].size();i++) 22 { 23 int p=v[u][i]; 24 if(vis[p]) continue; 25 vis[p]=1; 26 if(match[p]==-1||dfs(match[p])==1) 27 { 28 match[u]=p; 29 match[p]=u; 30 return 1; 31 } 32 } 33 return 0; 34 } 35 36 int main() 37 { 38 int sum=0; 39 init(); 40 for(int i=1;i<=n;i++) 41 { 42 if(match[i]==-1) 43 { 44 memset(vis,0,sizeof(vis)); 45 if (dfs(i)) sum++; 46 } 47 } 48 printf("%d\n",min(V+1,n+m-sum)); 49 return 0; 50 }
#include<cstdio> #include<cstring> using namespace std; const int N=305; const int inf=0X3f3f3f; int w[N][N]; int n,ans=0; int lx[N],ly[N],match[N],slack[N]; bool visx[N],visy[N]; void init() { for(int i=0;i<n;i++) visy[i]=0; for(int i=0;i<n;i++) visx[i]=0; } bool dfs(int u) { int Delta; visx[u]=1; for(int v=0;v<n;++v) { if(visy[v]) continue; Delta=lx[u]+ly[v]-w[u][v]; if(Delta==0) { visy[v]=1; if(match[v]==-1||dfs(match[v])) { match[v]=u; return true; } } else if(slack[v] > Delta) slack[v] = Delta; } return false; } void KM() { for(int x=0;x<n;++x) { for(int y=0;y<n;++y) slack[y]=inf; while(true) { init(); if(dfs(x)) break; int delta=inf; for(int j=0;j<n;++j) if(!visy[j]&&delta>slack[j]) delta=slack[j]; for(int i=0;i<n;++i) if(visx[i]) lx[i]-=delta; for(int j=0;j<n;++j) { if(visy[j]) ly[j]+=delta; else slack[j]-=delta;//important } } } } int main() { while(scanf("%d",&n)!=EOF) { memset(match,-1,sizeof(match)); memset(ly,0,sizeof(ly)); for(int i=0;i<n;++i) match[i]=-1; for(int i=0;i<n;++i) { for(int j=0;j<n;++j) { scanf("%d",&w[i][j]); } } for(int i=0;i<n;++i) { lx[i]=-inf; for(int j=0;j<n;j++) if(lx[i]<w[i][j]) lx[i]=w[i][j]; } KM(); ans=0; for(int i=0;i<n;++i) { if(match[i]!=-1) ans+=w[match[i]][i]; } printf("%d\n",ans); } return 0; }