点击打开链接
直接模版。。
#include <stdio.h> #include <memory.h> #define Min(X,Y) X<=Y?X:Y; #define SIZE 305 #define INF 0x7f7f7f7f long n; long match[SIZE],edge[SIZE][SIZE],lx[SIZE],ly[SIZE],slack[SIZE]; char vstx[SIZE],vsty[SIZE]; bool DFS(long x){ long i; vstx[x]=1; //访问标志置1 for(i=0;i<n;i++){ if(vsty[i]==0&&edge[x][i]==lx[x]+ly[i]){ vsty[i]=1; if(match[i]==-1||DFS(match[i])){ //i没被访问过可直接构造或者通过该点能间接构造增广路 match[i]=x; return true; } } else if(edge[x][i]!=lx[x]+ly[i]) //不能构造增广路,松驰对应值 slack[i]=Min(slack[i],lx[x]+ly[i]-edge[x][i]); } return false; } long KM(){ long i,j,sum,mn; memset(match,-1,sizeof(match[0])*n); for(i=0;i<n;i++){ while(1){ memset(vstx,0,sizeof(vstx[0])*n); memset(vsty,0,sizeof(vsty[0])*n); memset(slack,0x7f,sizeof(slack[0])*n); //松驰值初始化无穷大 if(DFS(i)==1) //有增广路则break,否则修改顶标值 break; mn=INF; for(j=0;j<n;j++) if(vsty[j]==0) mn=Min(mn,slack[j]); //求最小的松弛值 for(j=0;j<n;j++){ if(vstx[j]==1) lx[j]-=mn; //交错子树中X中的顶标-mn if(vsty[j]==1) ly[j]+=mn; //交错子树中Y中的顶标+mn if(vsty[j]==0) slack[j]-=mn; //非交错子树中的Y的顶点松驰值-mn } } } sum=0; for(i=0;i<n;i++) sum+=lx[i]+ly[i];//加上所有顶标值 return sum; } int main(){ //freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); long i,j; while(scanf("%ld",&n)!=EOF){ memset(ly,0,sizeof(ly[0])*n); for(i=0;i<n;i++){ for(j=0;j<n;j++){ scanf("%ld",&edge[i][j]); if(lx[i]<edge[i][j]) lx[i]=edge[i][j]; } } printf("%ld\n",KM()); } return 0; }