SOJ 1303. Job Assignment 与 KM算法模版

2 篇文章 0 订阅

Sicily 1303 Job Assignment


题目链接: http://soj.sysu.edu.cn/1303



1303. Job Assignment

Constraints

Time Limit: 1 secs, Memory Limit: 32 MB

Description

One problem comes up when we are trying to assign jobs about GDCPC’2003 (ZSUCPC’2003) to staffs. Because some of them complain that the tasks assigned to them are so bother. This emotion will lead to very bad effect in sequence. So we try to satisfy every staff as possible as we can. At first, we make an investigation to get the information about staffs’ attitude towards every task. And then we evaluate each attitude as a point (a positive integer number not larger than 100). The higher the point is, the more the staff is satisfied. Because the staffs are very busy, they have only a little leisure time to finish the task. So we just assign one task to one person, of course, one task can not be assigned to different persons. Now we give you all the points and hope you can help us to assign the tasks to make the sum of the points which correspond the assignment is maximum.

Input

Input will contain several test cases. The first line of each test case only contains one integer number N (0≤N≤100). N is the number of staffs, also is the number of tasks. And then, the following N lines describe staffs’ attitude. Each line contains n positive integer numbers. The jth number in the ith line describes ith staff‘s attitude to the jth task.

N=0 indicates the end of input file.

Output

For each test case you should output one line, and just one number in this line. The number is the maximum.

Sample Input

2
10 90
80 100
3
50 60 70
70 75 80
80 90 100
0

Sample Output

170
230



这里可以看出是一个二分图带权最大匹配的问题,KM算法我一直都理解不能,这里记一个模版以便以后使用。


#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string>
#include <stack>
#include <cstring>
#include <vector>
#include <climits>

using namespace std;

const int MAX_N = 102;
const int _INF = INT_MAX / 2;

int Nx, Ny;//维度大小
int match[MAX_N];//Y的匹配 Y->X
int lx[MAX_N], ly[MAX_N];//顶标
int slack[MAX_N];//寻找不到的情况下暂存差值的最小值
int weight[MAX_N][MAX_N];//路径长
bool visx[MAX_N], visy[MAX_N];//标记访问到

bool dfs(int x) {
	visx[x] = true;
	for (int y = 0; y < Ny; ++y) {
		if (visy[y])
			continue;
		int gap = lx[x] + ly[y] - weight[x][y];
		if (gap == 0) {
			visy[y] = true;
			if (match[y] == -1 || dfs(match[y])) {
				match[y] = x;
				return true;
			}
		}
		else slack[y] = min(gap, slack[y]);
	}
	return false;
}

int KM(void) {
	//初始化ly,match
	memset(ly, 0, sizeof(ly));
	for (int i = 0; i < MAX_N; ++i) {
		match[i] = -1;
	}
	//初始化lx为边权重最大的
	for (int i = 0; i < Nx; ++i) {
		lx[i] = weight[i][0];
		for (int j = 1; j < Ny; ++j)
			if (lx[i] < weight[i][j])
				lx[i] = weight[i][j];
	}

	for (int x = 0; x < Nx; ++x) {
		for (int y = 0; y < Ny; ++y)
			slack[y] = _INF;
		for (;;) {
			memset(visx, 0, sizeof(visx));
			memset(visy, 0, sizeof(visy));
			//如果找到增广路
			if (dfs(x))
				break;
			//未找到时修改条件
			int d = _INF;
			for (int y = 0; y < Ny; ++y) {
				if (visy[y] == false && d > slack[y])
					d = slack[y];
			}
			for (int i = 0; i < Nx; ++i) {
				if (visx[i])
					lx[i] -= d;
			}
			for (int y = 0; y < Ny; ++y) {
				if (visy[y])
					ly[y] += d;
				else
					slack[y] -= d;
			}
		}
	}

	int res = 0;
	for (int i = 0; i < Ny; ++i) {
		if (match[i] != -1)
			res += weight[match[i]][i];
	}
	return res;
}

KM算法的主体部分已经出来了,

剩下部分调用即可


int main() {
	int N;
	while (cin >> N && N) {
		Nx = Ny = N;
		for (int x = 0; x < Nx; ++x) {
			for (int y = 0; y < Ny; ++y) {
				scanf("%d", &weight[x][y]);
			}
		}
		printf("%d\n", KM());
	}
	return 0;
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值