KM算法 (HDU 2255 1533 1853 3488 3435 2426 2853)

http://philoscience.iteye.com/blog/1754498   讲解

讲的很详细很好


HDU 2255

#include <iostream>
#include <cstring>
#define maxnum 305
#define INF (1<<31)-1
using namespace std;

int vx[maxnum],vy[maxnum];
int link[maxnum];
int head[maxnum];
int lx[maxnum],ly[maxnum];
int w[maxnum][maxnum];
int slack[maxnum];
int cnt;
int nx,ny;

void init()
{
	cnt = 0;
	memset(link,-1,sizeof(link));
	memset(lx,0,sizeof(lx));
	memset(ly,0,sizeof(ly));
}

int find(int x)
{
	vx[x] = 1;
	for(int y=0;y<ny;y++)
	{
		if(vy[y])
			continue;

		int t = lx[x]+ly[y]-w[x][y];
		if(t == 0)
		{
			vy[y] = 1;
			if(link[y] == -1 || find(link[y]))
			{
				link[y]  =x;
				return 1;
			}
		}
		else
			if(slack[y] > t)
				slack[y] = t;
	}

	return 0;
}

int KM()
{
	int i,j;

	for(i=0;i<nx;i++)
	{
		for(j=0;j<ny;j++)
			if(lx[i] < w[i][j])
				lx[i] = w[i][j];
	}

	for(int x=0;x<nx;x++)
	{
		for(i=0;i<ny;i++)
			slack[i] = INF;

		while(1)
		{
			memset(vx,0,sizeof(vx));
			memset(vy,0,sizeof(vy));

			if(find(x))
				break;

			int d = INF;
			for(i=0;i<ny;i++)
			{
				if(!vy[i] && d > slack[i])
					d = slack[i];
			}

			for(i=0;i<nx;i++)
			{
				if(vx[i])
					lx[i] -= d;
			}

			for(i=0;i<ny;i++)
			{
				if(vy[i])
					ly[i] += d;
				else
					slack[i] -= d;
			}
		}
	}

	int res = 0;
	for(i=0;i<ny;i++)
	{
		if(link[i] > -1)
			res += w[link[i]][i];
	}

	return res;
}

int main()
{
	int i,j,k,kk;
	int a,b;
	int len;
	int u,v;
	int p,n,N,m;

	while(~scanf("%d",&n))
	{
		nx = ny = n;

		init();

		for(i=0;i<n;i++)
		{
			for(j=0;j<n;j++)
			{
				scanf("%d",&w[i][j]);
			}
		}

		printf("%d\n",KM());
	}
	return 0;
}

HDU  1533

#include <iostream>
#include <cstring>
#define maxnum 205
#define INF (1<<31)-1
using namespace std;

int vx[maxnum],vy[maxnum];
int link[maxnum];
int head[maxnum];
int lx[maxnum],ly[maxnum];
int w[maxnum][maxnum];
int slack[maxnum];
int cnt;
int nx,ny;

struct node
{
	int x,y;
}man[maxnum],house[maxnum];

void init()
{
	cnt = 0;
	memset(link,-1,sizeof(link));
	memset(lx,0,sizeof(lx));
	memset(ly,0,sizeof(ly));
}

int find(int x)
{
	vx[x] = 1;
	for(int y=0;y<ny;y++)
	{
		if(vy[y])
			continue;

		int t = lx[x]+ly[y]-w[x][y];
		if(t == 0)
		{
			vy[y] = 1;
			if(link[y] == -1 || find(link[y]))
			{
				link[y]  =x;
				return 1;
			}
		}
		else
			if(slack[y] > t)
				slack[y] = t;
	}

	return 0;
}

int KM()
{
	int i,j;

	for(i=0;i<nx;i++)
	{
		for(j=0;j<ny;j++)
			if(lx[i] < w[i][j])
				lx[i] = w[i][j];
	}

	for(int x=0;x<nx;x++)
	{
		for(i=0;i<ny;i++)
			slack[i] = INF;

		while(1)
		{
			memset(vx,0,sizeof(vx));
			memset(vy,0,sizeof(vy));

			if(find(x))
				break;

			int d = INF;
			for(i=0;i<ny;i++)
			{
				if(!vy[i] && d > slack[i])
					d = slack[i];
			}

			for(i=0;i<nx;i++)
			{
				if(vx[i])
					lx[i] -= d;
			}

			for(i=0;i<ny;i++)
			{
				if(vy[i])
					ly[i] += d;
				else
					slack[i] -= d;
			}
		}
	}

	int res = 0;
	for(i=0;i<ny;i++)
	{
		if(link[i] > -1)
			res += w[link[i]][i];
	}

	return res*(-1);
}

int main()
{
	int i,j,k,kk;
	int a,b;
	int len;
	int u,v;
	int p,n,N,m;
	char c;

	while(~scanf("%d%d%*c",&n,&m),n&&m)
	{
		init();
		k = kk = 0;

		for(i=0;i<n;i++)
		{
			for(j=0;j<m;j++)
			{
				scanf("%c",&c);
				if(c == 'm')
				{
					man[k].x = i;
					man[k++].y = j;
				}
				else
				{
					if(c == 'H')
					{
						house[kk].x = i;
						house[kk++].y = j;
					}
				}
			}
			getchar();
		}

		for(i=0;i<k;i++)
		{
			for(j=0;j<k;j++)
			{
				w[i][j] = abs(man[i].x - house[j].x) + abs(man[i].y - house[j].y);
				w[i][j] *= (-1);
			}
		}

		nx = ny = k;

		printf("%d\n",KM());
	}
	return 0;
}

HDU  1853

#include <iostream>
#include <cstring>
#define maxnum 205
#define INF 0x5f5f5f
using namespace std;

int vx[maxnum],vy[maxnum];
int link[maxnum];
int head[maxnum];
int lx[maxnum],ly[maxnum];
int w[maxnum][maxnum]; 
int slack[maxnum];
int nx,ny;

void init()
{
	memset(link,-1,sizeof(link));
	memset(ly,0,sizeof(ly));
}

int find(int x)
{
	vx[x] = 1;
	for(int y=1;y<=ny;y++)
	{
		if(vy[y])
			continue;

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

		if(t == 0)
		{
			vy[y] = 1;
			if(link[y] == -1 || find(link[y]))
			{
				link[y]  = x;
				return 1;
			}
		}
		else
			if(slack[y] > t)
				slack[y] = t;
	}

	return 0;
}

int KM()
{
	int i,j;

	for(i=1;i<=nx;i++)
	{
		lx[i] = -INF;
		for(j=1;j<=ny;j++)
			if(lx[i] < w[i][j])
				lx[i] = w[i][j];
	}

	for(int x=1;x<=nx;x++)
	{
		for(i=1;i<=ny;i++)
			slack[i] = INF;

		while(1)
		{
			memset(vx,0,sizeof(vx));
			memset(vy,0,sizeof(vy));

			if(find(x))
				break;

			int d = INF;
			for(i=1;i<=ny;i++)
			{
				if(!vy[i] && d > slack[i])
					d = slack[i];
			}

			for(i=1;i<=nx;i++)
			{
				if(vx[i])
					lx[i] -= d;
			}

			for(i=1;i<=ny;i++)
			{
				if(vy[i])
					ly[i] += d;
				else
					slack[i] -= d;
			}
		}
	}

	int res = 0;
	
	for(i=1;i<=ny;i++)
	{
		if(link[i] == -1 || w[link[i]][i] == -INF)
			return 1;
		else
			res += w[link[i]][i];
	}

	return res;
}

int main()
{
	int i,j,k,kk;
	int a,b,c;
	int len;
	int u,v;
	int p,n,N,m;

	while(~scanf("%d%d",&n,&m))
	{
		init();

		for(i=1;i<=n;i++)
			for(j=1;j<=n;j++)
				w[i][j] = -INF;

		for(i=0;i<m;i++)
		{
			scanf("%d%d%d",&a,&b,&c);
			if(w[a][b] < -c)
			    w[a][b] = -c;
		}

		nx = ny = n;

		printf("%d\n",-KM());
	}
	return 0;
}


HDU  3488

#include <iostream>
#include <cstring>
#define maxnum 205
#define INF 0x5f5f5f
using namespace std;

int vx[maxnum],vy[maxnum];
int link[maxnum];
int head[maxnum];
int lx[maxnum],ly[maxnum];
int w[maxnum][maxnum]; 
int slack[maxnum];
int nx,ny;

void init()
{
	memset(link,-1,sizeof(link));
	memset(ly,0,sizeof(ly));
}

int find(int x)
{
	vx[x] = 1;
	for(int y=1;y<=ny;y++)
	{
		if(vy[y])
			continue;

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

		if(t == 0)
		{
			vy[y] = 1;
			if(link[y] == -1 || find(link[y]))
			{
				link[y]  = x;
				return 1;
			}
		}
		else
			if(slack[y] > t)
				slack[y] = t;
	}

	return 0;
}

int KM()
{
	int i,j;

	for(i=1;i<=nx;i++)
	{
		lx[i] = -INF;
		for(j=1;j<=ny;j++)
			if(lx[i] < w[i][j])
				lx[i] = w[i][j];
	}

	for(int x=1;x<=nx;x++)
	{
		for(i=1;i<=ny;i++)
			slack[i] = INF;

		while(1)
		{
			memset(vx,0,sizeof(vx));
			memset(vy,0,sizeof(vy));

			if(find(x))
				break;

			int d = INF;
			for(i=1;i<=ny;i++)
			{
				if(!vy[i] && d > slack[i])
					d = slack[i];
			}

			for(i=1;i<=nx;i++)
			{
				if(vx[i])
					lx[i] -= d;
			}

			for(i=1;i<=ny;i++)
			{
				if(vy[i])
					ly[i] += d;
				else
					slack[i] -= d;
			}
		}
	}

	int res = 0;
	
	for(i=1;i<=ny;i++)
	{
		if(link[i] == -1 || w[link[i]][i] == -INF)
			return 1;
		else
			res += w[link[i]][i];
	}

	return res;
}

int main()
{
	int i,j,k,kk;
	int a,b,c;
	int len;
	int u,v;
	int p,n,N,m;

	scanf("%d",&N);
	while(N--)
	{
		init();
		scanf("%d%d",&n,&m);

		for(i=1;i<=n;i++)
			for(j=1;j<=n;j++)
				w[i][j] = -INF;

		for(i=0;i<m;i++)
		{
			scanf("%d%d%d",&a,&b,&c);
			if(w[a][b] < -c)
			    w[a][b] = -c;
		}

		nx = ny = n;

		printf("%d\n",-KM());
	}
	return 0;
}

HDU 3435

#include <iostream>
#include <cstring>
#define maxnum 1050
#define INF 0x5f5f5f
using namespace std;

int vx[maxnum],vy[maxnum];
int link[maxnum];
int head[maxnum];
int lx[maxnum],ly[maxnum];
int w[maxnum][maxnum]; 
int slack[maxnum];
int nx,ny;

void init()
{
	memset(link,-1,sizeof(link));
	memset(ly,0,sizeof(ly));
}

int find(int x)
{
	vx[x] = 1;
	for(int y=1;y<=ny;y++)
	{
		if(vy[y])
			continue;

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

		if(t == 0)
		{
			vy[y] = 1;
			if(link[y] == -1 || find(link[y]))
			{
				link[y]  = x;
				return 1;
			}
		}
		else
			if(slack[y] > t)
				slack[y] = t;
	}

	return 0;
}

int KM()
{
	int i,j;

	for(i=1;i<=nx;i++)
	{
		lx[i] = -INF;
		for(j=1;j<=ny;j++)
			if(lx[i] < w[i][j])
				lx[i] = w[i][j];
	}

	for(int x=1;x<=nx;x++)
	{
		for(i=1;i<=ny;i++)
			slack[i] = INF;

		while(1)
		{
			memset(vx,0,sizeof(vx));
			memset(vy,0,sizeof(vy));

			if(find(x))
				break;

			int d = INF;
			for(i=1;i<=ny;i++)
			{
				if(!vy[i] && d > slack[i])
					d = slack[i];
			}

			for(i=1;i<=nx;i++)
			{
				if(vx[i])
					lx[i] -= d;
			}

			for(i=1;i<=ny;i++)
			{
				if(vy[i])
					ly[i] += d;
				else
					slack[i] -= d;
			}
		}
	}

	int res = 0;
	
	for(i=1;i<=ny;i++)
	{
		if(link[i] == -1 || w[link[i]][i] == -INF)
			return 1;
		else
			res += w[link[i]][i];
	}

	return res;
}

int main()
{
	int i,j,k,kk;
	int a,b,c;
	int len;
	int u,v;
	int p,n,N,m;

	scanf("%d",&N);
	k=1;
	while(N--)
	{
		init();
		scanf("%d%d",&n,&m);

		for(i=1;i<=n;i++)
			for(j=1;j<=n;j++)
				w[i][j] = -INF;

		for(i=0;i<m;i++)
		{
			scanf("%d%d%d",&a,&b,&c);
			if(w[a][b] < -c)
			    w[a][b] = -c;
			if(w[b][a] < -c)
				w[b][a] = -c;
		}

		nx = ny = n;

		int t = KM();
		printf("Case %d: ",k++);
		printf(t>0?"NO\n":"%d\n",-t);
	}
	return 0;
}

HDU  2426

#include <iostream>
#include <cstring>
#define maxnum 1050
#define INF 0x5f5f5f
using namespace std;

int vx[maxnum],vy[maxnum];
int link[maxnum],linkx[maxnum];
int head[maxnum];
int lx[maxnum],ly[maxnum];
int w[maxnum][maxnum]; 
int slack[maxnum];
int nx,ny;

void init()
{
	memset(link,-1,sizeof(link));
	memset(linkx,0,sizeof(linkx));
	memset(lx,0,sizeof(lx));
	memset(ly,0,sizeof(ly));
}

int find(int x)
{
	vx[x] = 1;
	for(int y=1;y<=ny;y++)
	{
		if(vy[y])
			continue;

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

		if(t == 0)
		{
			vy[y] = 1;
			if(link[y] == -1 || find(link[y]))
			{
				link[y]  = x;
				return 1;
			}
		}
		else
			if(slack[y] > t)
				slack[y] = t;
	}

	return 0;
}

int KM()
{
	int i,j;

	for(i=1;i<=nx;i++)
	{
		lx[i] = -INF;
		for(j=1;j<=ny;j++)
			if(lx[i] < w[i][j])
				lx[i] = w[i][j];
	}

	for(int x=1;x<=nx;x++)
	{
		for(i=1;i<=ny;i++)
			slack[i] = INF;

		while(1)
		{
			memset(vx,0,sizeof(vx));
			memset(vy,0,sizeof(vy));

			if(find(x))
				break;

			int d = INF;
			for(i=1;i<=ny;i++)
			{
				if(!vy[i] && d > slack[i])
					d = slack[i];
			}

			for(i=1;i<=nx;i++)
			{
				if(vx[i])
					lx[i] -= d;
			}

			for(i=1;i<=ny;i++)
			{
				if(vy[i])
					ly[i] += d;
				else
					slack[i] -= d;
			}
		}
	}

	int res = 0;
	
	for(i=1;i<=ny;i++)
	{
		if(link[i] > -1 && w[link[i]][i] != -INF)
		{
			res += w[link[i]][i];
			linkx[link[i]] = 1;
		}
	}

	for(i=1;i<=nx;i++)
		if(!linkx[i])
			return -1;

	return res;
}

int main()
{
	int i,j,k,kk;
	int a,b,c;
	int len;
	int u,v;
	int p,n,N,m;
	kk=1;
	while(~scanf("%d%d%d",&n,&m,&k))
	{
		init();
	

		for(i=1;i<=n;i++)
			for(j=1;j<=m;j++)
				w[i][j] = -INF;

		for(i=0;i<k;i++)
		{
			scanf("%d%d%d",&a,&b,&c);
			if(c < 0)
				continue;
			w[a+1][b+1] = c;
		}

		nx=n;ny=m;

		printf("Case %d: ",kk++);
		if(k==0)
			printf("-1\n");
		else
		     printf("%d\n",KM());
	}
	return 0;
}

HDU  2853

#include <iostream>
#include <cstring>
#define maxnum 1050
#define INF 0xffff5f
using namespace std;

int vx[maxnum],vy[maxnum],vis[maxnum];
int link[maxnum];
int head[maxnum];
int lx[maxnum],ly[maxnum];
int w[maxnum][maxnum]; 
int slack[maxnum];
int nx,ny;
int change;

void init()
{
	memset(link,-1,sizeof(link));
	memset(lx,0,sizeof(lx));
	memset(ly,0,sizeof(ly));
	memset(vis,0,sizeof(vis));
	change = 0;
}

int find(int x)
{
	vx[x] = 1;
	for(int y=1;y<=ny;y++)
	{
		if(vy[y])
			continue;

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

		if(t == 0)
		{
			vy[y] = 1;
			if(link[y] == -1 || find(link[y]))
			{
				link[y]  = x;
				return 1;
			}
		}
		else
			if(slack[y] > t)
				slack[y] = t;
	}

	return 0;
}

int KM()
{
	int i,j;

	for(i=1;i<=nx;i++)
	{
		for(j=1;j<=ny;j++)
			if(lx[i] < w[i][j])
				lx[i] = w[i][j];
	}

	for(int x=1;x<=nx;x++)
	{
		for(i=1;i<=ny;i++)
			slack[i] = INF;

		while(1)
		{
			memset(vx,0,sizeof(vx));
			memset(vy,0,sizeof(vy));

			if(find(x))
				break;

			int d = INF;
			for(i=1;i<=ny;i++)
			{
				if(!vy[i] && d > slack[i])
					d = slack[i];
			}

			for(i=1;i<=nx;i++)
			{
				if(vx[i])
					lx[i] -= d;
			}

			for(i=1;i<=ny;i++)
			{
				if(vy[i])
					ly[i] += d;
				else
					slack[i] -= d;
			}
		}
	}

	int res = 0;
	
	for(i=1;i<=ny;i++)
	{
		if(link[i] > -1)
		{
// 			if(link[i] != vis[i])
// 				change++;

			res += w[link[i]][i];
		}
	}

	return res;
}

int main()
{
	int i,j,k,kk;
	int a,b,c;
	int len;
	int u,v;
	int p,n,N,m;
	int sum;
	
	while(~scanf("%d%d",&n,&m))
	{
		init();

		for(i=1;i<=n;i++)
			for(j=1;j<=m;j++)
			{
				scanf("%d",&w[i][j]);
				w[i][j] *= 100;
			}

		for(i=1,sum=0;i<=n;i++)
		{
			scanf("%d",&k);
			sum += w[i][k];
			w[i][k]++;
		}

		nx=n;ny=m;
		kk = KM();

		printf("%d %d\n",n-kk%100,kk/100-sum/100);
	}

	return 0;
}


你可能感兴趣的:(KM算法)