题意:有K台挤奶机,C头奶牛,每个挤奶机每天只能为M头奶牛服务,下面给的K+C的矩阵,是形容相互之间的距离,求出来走最远的那头奶牛要走多远
输入数据:
第一行三个数 K, C, M
接下来是 (K+C)*(K+C)的矩阵
表示每个物体之间的距离, 0 表示两者之间是不通的。
挤奶机 1, 挤奶机2 .... 挤奶机 K, 奶牛1,奶牛2...奶牛M
题目思路:
对输入进来的数据先进行闭包传递,然后再对奶牛到挤奶机的距离进行二分枚举,枚举出来的值进行多重匹配
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
#include<vector>
#include<queue>
#include<cmath>
using namespace std;
#define INF 0x3fffffff
#define maxn 1255
int n, m, k;///n个挤奶机 m只奶牛 每台挤奶机最多挤 k只
bool vis[maxn];
int G[maxn][maxn], Dis[], DisNum;
vector<vector<int> > P;///用来保存匹配的数据 void Floyd()
{
int len = n + m;
DisNum = ;
for(int k=; k < len; k++)
{
for(int i=; i < len; i++)
{
for(int j=; j < len; j++)
G[i][j] = min(G[i][j], G[i][k]+G[k][j]);
}
} for(int i=; i<len; i++)
{
for(int j=; j<len; j++)
Dis[DisNum ++] = G[i][j];
}
}
bool Find(int u,int limt)
{
for(int i=; i<n; i++)
{
if(!vis[i] && G[u][i] <= limt)
{
vis[i] = true;
if(P[i].size() < k)
{
P[i].push_back(u);
return true;
}
for(int j=; j<P[i].size(); j++)
{
if( Find(P[i][j], limt) )
{
P[i].erase(P[i].begin()+j);
P[i].push_back(u);
return true;
}
}
}
}
return false;
} bool solve(int limt)
{
P.clear();
P.resize(n+);
for(int i=n; i<n+m; i++)
{
memset(vis, false, sizeof(vis));
if( !Find(i,limt) )
return false;
}
return true;
} int main()
{
while(scanf("%d %d %d", &n, &m, &k) != EOF)
{
for(int i=; i<n+m; i++)
{
for(int j=; j<n+m; j++)
{
scanf("%d", &G[i][j]);
if(!G[i][j]) G[i][j] = INF;
} }
Floyd();///先进行一下闭包传递
sort(Dis,Dis + DisNum);
int L = , R = DisNum - ; while(L < R)
{
int mid = (L + R) / ;
if( solve(Dis[mid]) )
R = mid;
else
L = mid + ;
}
printf("%d\n", Dis[R]);
}
return ;
}