题目链接:http://poj.org/problem?id=2112

       题意是有k台挤奶机,c头奶牛,每台挤奶机最多可以给m奶头牛挤奶,1--k是挤奶机的编号,k+1--k+c是奶牛的编号,然后输入一个邻接矩阵,表示它们任意两点间的距离,问这些奶牛去挤奶机的过程中,跑的最远的一头奶牛的最小距离是多少。

       思路就是我们先存边,然后对于距离为0的是不可到达的边,赋值为inf就好,然后先跑一遍Floyd求出任意两点的最短距离,然后用二分去枚举上下界,去判断是否符合二分图的多重匹配就好了。


AC代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <vector>
#define maxn 250
#define inf 0x3f3f3f3f
using namespace std;
struct Node{
	int cnt;
	int k[maxn];
}link[maxn];
bool maps[maxn][maxn];
bool vis[maxn];
int pre[maxn][maxn];
int k,c,m,Max;

void Floyd(){
	for(int p=1;p<=k+c;p++){
		for(int i=1;i<=k+c;i++){
			for(int j=1;j<=k+c;j++){
				if(pre[i][j] > pre[i][p] + pre[p][j]){
					pre[i][j] = pre[i][p] + pre[p][j];
				}
			}
		}
	}
}

bool dfs(int u){
	for(int i=1;i<=k;i++){
		if(vis[i] == false && maps[i][u] == true){
			vis[i] = true;
			if(link[i].cnt < m){
				link[i].k[ ++ link[i].cnt ] = u;
				return true;
			}
			for(int j=1;j<=link[i].cnt;j++){
				if(dfs(link[i].k[j])){
					link[i].k[j] = u;
					return true;
				}
			}
		}
	}
	return false;
}

bool solve(int limit){
	memset(maps, false, sizeof(maps));
	memset(link, 0 ,sizeof(link));
	for(int i=1;i<=k;i++){
		for(int j=k+1;j<=k+c;j++){
			if(pre[i][j] <= limit){
				maps[i][j-k] = true;
			}
		}
	}
	for(int i=1;i<=c;i++){
		memset(vis,false,sizeof(vis));
		if(!dfs(i)) return false;
	}
	return true;
}

int main()
{
	while(scanf("%d%d%d",&k,&c,&m) != -1){
		Max = 0;
		for(int i=1;i<=k+c;i++){
			for(int j=1;j<=k+c;j++){
				scanf("%d",&pre[i][j]);
				if(pre[i][j] == 0) pre[i][j] = inf;
			}
		}
		Floyd();
		for(int i=1;i<=k;i++){
			for(int j=k+1;j<=k+c;j++){
				Max = max(Max, pre[i][j]);
			}
		}
		int l = 0, r = Max, mid;
		// int ans = Max;
		while(l < r){
			mid = (l + r) >> 1;
			if(solve(mid)){
				r = mid;
				// ans = mid;
			}
			else l = mid + 1;
		}
		printf("%d\n", r);
	}
	return 0;
}