Description
FJ has moved his K (1 <= K <= 30) milking machines out into the cow
pastures among the C (1 <= C <= 200) cows. A set of paths of various
lengths runs among the cows and the milking machines. The milking
machine locations are named by ID numbers 1..K; the cow locations are
named by ID numbers K+1..K+C.Each milking point can “process” at most M (1 <= M <= 15) cows each
day.Write a program to find an assignment for each cow to some milking
machine so that the distance the furthest-walking cow travels is
minimized (and, of course, the milking machines are not overutilized).
At least one legal assignment is possible for all input data sets.
Cows can traverse several paths on the way to their milking machine.Input
*Line 1: A single line with three space-separated integers: K, C, and M.
*Lines 2.. …: Each of these K+C lines of K+C space-separated integers describes the distances between pairs of various entities.
The input forms a symmetric matrix. Line 2 tells the distances from
milking machine 1 to each of the other entities; line 3 tells the
distances from machine 2 to each of the other entities, and so on.
Distances of entities directly connected by a path are positive
integers no larger than 200. Entities not directly connected by a path
have a distance of 0. The distance from an entity to itself (i.e., all
numbers on the diagonal) is also given as 0. To keep the input lines
of reasonable length, when K+C > 15, a row is broken into successive
lines of 15 numbers and a potentially shorter line to finish up a row.
Each new row begins on its own line.Output
A single line with a single integer that is the minimum possible total
distance for the furthest walking cow.Sample Input 2 3 2 0 3 2 1 1 3 0 3 2 0 2 3 0 1 0 1 2 1 0 2 1 0 0 2 0
Sample Output 2
1、每头牛走到挤奶器,走的过程不会占用挤奶器的“空间”,所以奶牛到挤奶器的路径可以直接抽象成一条长度为路径长度的边。N+C<=230所以显然可以用floyd预处理出来。
2、新建超级源汇,S到奶牛连边,挤奶器到T连边,奶牛到挤奶器按照上面求出的路径连权值为1费用为路径长度的边。
3、二分最长路径,跑最大流,如果奶牛到挤奶器的费用大于mid则不走该边,求出一个使最大流等于C的mid最小值即为答案。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
const int maxn=240,maxm=108000,inf=0x3fffffff;
int G[240][240];
int head[maxn],ver[maxm],e[maxm],b[maxm],c[maxm],next[maxm];
int d[maxn];
int maxl=0,tot=1,K,C,M,s,t,mid;
void add (int u,int v,int w,int cost=0) {
ver[++tot]=v;e[tot]=b[tot]=w;c[tot]=cost;next[tot]=head[u];head[u]=tot;
ver[++tot]=u;e[tot]=b[tot]=0;c[tot]=cost;next[tot]=head[v];head[v]=tot;
}
bool bfs () {
queue<int> q;
memset(d,0,sizeof(d));
q.push(s); d[s]=1;
while (!q.empty()) {
int x=q.front(); q.pop();
for (int i=head[x];i;i=next[i])
if (e[i]&&!d[ver[i]]&&c[i]<=mid) {
q.push(ver[i]);
d[ver[i]]=d[x]+1;
if (ver[i]==t) return 1;
}
}
return 0;
}
int dinic (int x,int f) {
int rest=f;
if (x==t) return f;
for (int i=head[x];i&&rest;i=next[i])
if (e[i]&&d[ver[i]]==d[x]+1&&c[i]<=mid) {
int now=dinic(ver[i],min(e[i],rest));
if (!now) d[ver[i]]=0;//
e[i]-=now;
e[i^1]+=now;
rest-=now;
}
return f-rest;
}
void floyd () {
int i,j,k;
for (k=1;k<=K+C;k++)
for (i=1;i<=K+C;i++)
for (j=1;j<=K+C;j++)
G[i][j]=min(G[i][k]+G[k][j],G[i][j]);
}
bool checker () {
int tmp=0,maxflow=0;
memcpy(e,b,sizeof(b));
while (bfs())
while (tmp=dinic(s,inf)) maxflow+=tmp;
if (maxflow==C) return 1;
return 0;
}
void build () {
int num=K+C;
for (int i=K+1;i<=num;i++)
for (int j=1;j<=K;j++)
if (G[i][j]!=inf) {
maxl=max(maxl,G[i][j]);
add(i,j,1,G[i][j]);
}
}
int main () {
scanf("%d%d%d",&K,&C,&M);
for (int i=1;i<=K+C;i++)
for (int j=1;j<=K+C;j++)
G[i][j]=inf;
for (int i=1;i<=K+C;i++)
for (int j=1;j<=K+C;j++) {
scanf("%d",&G[i][j]);
if (!G[i][j]) G[i][j]=inf;
//注意数据中不连通的点距离为0
if (i==j) G[i][j]=0;
}
floyd();
build();
s=0,t=K+C+1;
for (int i=1;i<=K;i++) add(i,t,M);
for (int i=K+1;i<=K+C;i++) add(s,i,1);
int L=0,R=maxl;//
while (L<R) {
mid=(L+R)>>1;
if (checker()) R=mid;
else L=mid+1;
}
printf("%d",L);
}