带权二分图的最大权匹配 KM算法模版
下面是kuangbin大神的模版,已通过西电oj1048的测试
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #include<vector> #include<stack> #include<queue> #include<set> #include<map> #include<string> #include<math.h> #include<cctype> using namespace std; typedef long long ll; const int maxn=550; const int INF=(1<<29); const double EPS=0.0000000001; const double Pi=acos(-1.0); int G[maxn][maxn]; int m; int nx,ny; int link[maxn],lx[maxn],ly[maxn]; int slack[maxn]; bool visx[maxn],visy[maxn]; bool dfs(int x) { visx[x]=1; for(int y=0;y<ny;y++){ if(visy[y]) continue; int tmp=lx[x]+ly[y]-G[x][y]; if(tmp==0){ visy[y]=1; if(link[y]==-1||dfs(link[y])){ link[y]=x; return true; } } else if(slack[y]>tmp) slack[y]=tmp; } return false; } int KM() { memset(link,-1,sizeof(link)); memset(ly,0,sizeof(ly)); for(int i=0;i<nx;i++){ lx[i]=-INF; for(int j=0;j<ny;j++){ if(G[i][j]>lx[i]) lx[i]=G[i][j]; } } for(int x=0;x<nx;x++){ for(int i=0;i<ny;i++) slack[i]=INF; while(1){ memset(visx,0,sizeof(visx)); memset(visy,0,sizeof(visy)); if(dfs(x)) break; int d=INF; for(int i=0;i<ny;i++){ if(!visy[i]&&d>slack[i]) d=slack[i]; } for(int i=0;i<nx;i++){ if(visx[i]) lx[i]-=d; } for(int i=0;i<ny;i++){ if(visy[i]) ly[i]+=d; else slack[i]-=d; } } } int res=0; for(int i=0;i<ny;i++){ if(link[i]!=-1) res+=G[link[i]][i]; } return res; } int main() { while(cin>>nx>>ny){ memset(G,0,sizeof(G)); cin>>m; while(m--){ int u,v; scanf("%d%d",&u,&v); G[u][v]=1; } cout<<KM()<<endl; } return 0; }
时间: 2024-11-05 17:31:14