KM模板

O(n^3)的复杂度,解决最佳完备匹配问题。

 

#include <cstdio>

#include <cstring>

using namespace std;



const int maxn=160,OO=(~(0U))>>1;

int w[maxn][maxn];

int lx[maxn],ly[maxn];

int linky[maxn];

int visx[maxn],visy[maxn];

int N;

int slack[maxn];



void input(){

	scanf("%d",&N);

	for(int i=0;i<N;++i)

		for(int j=0;j<N;++j)

			scanf("%d",&w[i][j]);

}

bool find(int x){

	visx[x]=true;

	for(int y=0;y<N;++y){

		if(visy[y])continue;

		int t=lx[x]+ly[y]-w[x][y];

		if(t==0){

			visy[y]=true;

			if(linky[y]==-1||find(linky[y])){

				linky[y]=x;

				return true;

			}

		}

		else{

			if(slack[y]>t)

				slack[y]=t;

		}

	}

	return false;

}

void KM(){

	memset(linky,-1,sizeof(linky));

	memset(lx,0,sizeof(lx));

	memset(ly,0,sizeof(ly));

	for(int i=0;i<N;++i)

		for(int j=0;j<N;++j)

			if(w[i][j]>lx[i])

				lx[i]=w[i][j];

	for(int x=0;x<N;++x){

		for(int i=0;i<N;++i)

			slack[i]=OO;

		while(1){

			memset(visx,0,sizeof(visx));

			memset(visy,0,sizeof(visy));

			if(find(x))break;

			int d=OO;

			for(int i=0;i<N;++i){

				if(!visy[i])

					if(d>slack[i])

						d=slack[i];

			}

			for(int i=0;i<N;++i){

				if(visx[i])

					lx[i]-=d;

			}

			for(int i=0;i<N;++i){

				if(visy[i])

					ly[i]+=d;

				else

					slack[i]-=d;   //不太明白slack的操作

			}

		}

	}

}

void output(){

	int res=0;

	for(int j=0;j<N;++j){

		for(int i=0;i<N;++i)

			res+=w[i][j];

		res-=w[linky[j]][j];

	}

	printf("%d\n",res);

}

int main(){

	input();

	KM();

	output();

}

崔天翼神牛的模板http://cuitianyi.com/blog/%E6%B1%82%E6%9C%80%E5%A4%A7%E6%9D%83%E4%BA%8C%E5%88%86%E5%8C%B9%E9%85%8D%E7%9A%84km%E7%AE%97%E6%B3%95/

 

 

你可能感兴趣的:(模板)