POJ 2112:二分搜索 + 二分图多重匹配 + 最短路径

POJ 2112:二分搜索 + 二分图多重匹配 + 最短路径

最近,在复习一些图论的算法,找了些图论的题做一下。POJ 2112这题挺有代表性的,用到蛮多知识点。

题目:http://acm.pku.edu.cn/JudgeOnline/problem?id=2112

解题思路:求得每只牛与各机器的最短距离(Floyd);二分解空间;用修改后的匈牙利算法看C只牛是否能被完全匹配来判断解的可行性。

 



#include <cstring>
#include <cstdio>

namespace std{}
using namespace std;

#define INF 100000000
int dis[232][232], link[31][16], vlink[31], k, c, m, s;
bool g[31][201], b[31];

void input()
{
	scanf("%d%d%d", &k, &c, &m);
	s = k + c;
	for(int i = 0; i < s; ++i)
		for(int j = 0; j < s; ++j)
		{
			scanf("%d", &dis[i][j]);
			if(dis[i][j] == 0)
				dis[i][j] = INF;
		}
}

void floyd()
{
	for(int x = 0; x < s; ++x)
		for(int i = 0; i < s; ++i)
			for(int j = 0; j < s; ++j)
				if(dis[i][j] > dis[i][x] + dis[x][j])
					dis[i][j] = dis[i][x] + dis[x][j];
}

bool findroad(int p)
{
	for(int i = 0; i < k; ++i)
	{
		if(g[i][p] && !b[i])
		{
			b[i] = true;
			if(vlink[i] < m)
			{
				link[i][vlink[i]++] = p;
				return true;
			}
			for(int j = 0; j < vlink[i]; ++j)
				if(findroad(link[i][j])) {
					link[i][j] = p;
					return true;
				}
		}
	}
	return false;
}

bool isOK(int mid)
{
	int i, j;
	memset(g, false, sizeof(g));
	memset(link, 0, sizeof(link));
	memset(vlink, 0, sizeof(vlink));
	for(i = 0; i < k; ++i)
		for(j = k; j < s; ++j)
			if(dis[i][j] <= mid)
				g[i][j - k] = true;
	for(i = 0; i < c; ++i) {
		memset(b, false, sizeof(b));
		if(!findroad(i))
			return false;
	}
	return true;
}

void binary_search()
{
	int min, max, mid;
	min = max = 0;
	for(int i = 0; i < k; ++i)
		for(int j = k; j < s; ++j)
			max = (dis[i][j] > max) ? dis[i][j] : max;

	while(min < max)
	{
		mid = (min + max) / 2;
		if(isOK(mid)) {
			max = mid;
		} else {
			min = mid + 1;
		}
	}
	printf("%d/n", max);
}

int main()
{
	input();
	floyd();
	binary_search();
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值