题目大意:有k个奶牛加工机器和c头奶牛,每个奶牛只能去一个机器,每个机器最多只能加工m头奶牛,并且给出所有点的邻接矩阵,问使得所有奶牛都被加工的时候,其中奶牛走的最远的路最小是多少;
题目解析:源 容量1 ->牛 容量1 -> 机器 容量m ->汇;先用floyd把所有点的最短路求出来,之后二分最长路的最小值即可;
AC代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<vector>
#include<queue>
using namespace std;
const int inf=0x3fffffff;
const int maxn=40070;
struct node
{
int to,cap,rev;
node(int a,int b,int c)
{
to=a;
cap=b;
rev=c;
}
};
vector<node>vec[maxn];
int pre[maxn],iter[maxn],graph[301][301],k,c,m;
bool vis[maxn];
void add_edge(int from,int to,int cost)
{
vec[from].push_back(node(to,cost,vec[to].size()));
vec[to].push_back(node(from,0,vec[from].size()-1));
}
void bfs(int s){
memset(pre,-1,sizeof(pre));
queue<int>que;
pre[s]=0;que.push(s);
while(!que.empty()){
int v=que.front();que.pop();
for(int i=0;i<vec[v].size();i++){
node &e=vec[v][i];
if(e.cap>0&&pre[e.to]<0){
pre[e.to]=pre[v]+1;
que.push(e.to);
}
}
}
}
int dfs(int v,int t,int f){
if(v==t) return f;
for(int &i=iter[v];i<vec[v].size();i++){
node &e=vec[v][i];
if(e.cap>0&&pre[v]<pre[e.to]){
int d=dfs(e.to,t,min(f,e.cap));
if(d>0){
e.cap-=d;
vec[e.to][e.rev].cap+=d;
return d;
}
}
}
return 0;
}
int max_flow(int u,int v)
{
int flow=0;
while(1)
{
bfs(u);
if(pre[v]<0) return flow;
memset(iter,0,sizeof(iter));
int f;
while((f=dfs(u,v,inf))>0) flow+=f;
}
}
bool ok(int pos)
{
int i,j;
for(i=0;i<maxn;i++)
vec[i].clear();
for(i=k+1;i<=k+c;i++)
{
add_edge(0,i,1);
}
for(i=1;i<=k;i++)
add_edge(i,k+c+1,m);
for(i=k+1;i<=k+c;i++)
{
for(j=1;j<=k;j++)
{
if(graph[j][i]<=pos)
{
add_edge(i,j,1);
}
}
}
if(max_flow(0,k+c+1)==c) return 1;
else return 0;
}
int main()
{
int i,p,j;
while(scanf("%d%d%d",&k,&c,&m)!=EOF)
{
for(i=1;i<=k+c;i++)
{
for(j=1;j<=k+c;j++)
{
int temp;
scanf("%d",&temp);
if(temp==0)
graph[i][j]=inf;
else
graph[i][j]=temp;
}
}
int ans=-1;
for(p=1;p<=k+c;p++)
{
for(i=1;i<=k+c;i++)
{
if(graph[i][p]==inf) continue;
for(j=1;j<=k+c;j++)
{
if(graph[p][j]==inf||i==j) continue;
graph[i][j]=min(graph[i][j],graph[i][p]+graph[p][j]);
ans=max(ans,graph[i][j]);
}
}
}
int l=1,r=ans;
while(l<=r)
{
int m=(l+r)>>1;
if(!ok(m))
{
l=m+1;
}
else
{
r=m-1;
ans=m;
}
}
printf("%d\n",ans);
}
return 0;
}