题意: 给你一个带权的二分图,求该二分图的最优匹配权值
思路:左点集代表村名,右点集代表房子,最优匹配 KM 模板题。。。
#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()
{
int n;
while(scanf("%d",&n)!=EOF){
ny=nx=n;
memset(G,0,sizeof(G));
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
scanf("%d",&G[i][j]);
cout<<KM()<<endl;
}
return 0;
}
/*
_ooOoo_
o8888888o
88" . "88
(| -_- |)
O\ = /O
____/`---'\____
.' \\| |// `.
/ \\||| : |||// \
/ _||||| -:- |||||- \
| | \\\ - /// | |
| \_| ''\---/'' | |
\ .-\__ `-` ___/-. /
___`. .' /--.--\ `. . __
."" '< `.___\_<|>_/___.' >'"".
| | : `- \`.;`\ _ /`;.`/ - ` : | |
\ \ `-. \_ __\ /__ _/ .-` / /
======`-.____`-.___\_____/___.-`____.-'======
`=---='
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The program have no BUG.
*/