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;
}
本文介绍了解决POJ2112问题的方法,包括使用Floyd算法计算最短路径、通过二分图匹配寻找可行解以及采用二分搜索确定最优解。代码示例清晰展示了整个解题过程。
813

被折叠的 条评论
为什么被折叠?



