poj 2112 Optimal Milking 网络流 最大流
题目大意:农场有k个挤奶器,每个挤奶器最多容纳m头奶牛,所有奶牛和挤奶器之间的距离已知,安排奶牛挤奶方案使得所有奶牛中走的最大距离最小化。
利用最大流来做,奶牛和挤奶器看做图中节点,先用floyd算出每个节点之间的最小距离,二分最大距离d,然后建图,边长大于d的都去掉,然后建立网络,引入源点和汇点,源点到每个奶牛节点连接一条容量为一的边,挤奶器节点与汇点连接一条容量为m的边,奶牛节点与挤奶器节点间连接容量为一的边(如果之间有边的话),然后求最大流,不断二分。
代码为dinic算法
#include <stdio.h>
#include <string.h>
#define MAX 300
#define INF 10000000
int dis[MAX][MAX],map[MAX][MAX];
bool sign[MAX][MAX],used[MAX];
int K,C,n,M;
int min(int a,int b)
{
if(a>b)
return b;
else return a;
}
void build(int mid)
{
int i,j;
memset(map,0,sizeof(map));
for(i=K+1;i<=n;i++) map[0][i]=1;
for(i=1;i<=K;i++) map[i][n+1]=M;
for(i=K+1;i<=n;i++)
{
for(j=1;j<=K;j++)
if(dis[i][j]<=mid)
map[i][j]=1;
}
}
bool bfs()
{
memset(used,0,sizeof(used));
memset(sign,0,sizeof(sign));
int queue[100*MAX]={0};
queue[0]=0;
used[0]=1;
int t=1,f=0;
while(f<t)
{
for(int i=0;i<=n+1;i++)
{
if(!used[i]&&map[queue[f]][i])
{
queue[t++]=i;
used[i]=1;
sign[queue[f]][i]=1;
}
}
f++;
}
if(used[n+1]) return true;
else return false;
}
int dfs(int v,int sum)
{
int i,s,t;
if(v==n+1) return sum;
s=sum;
for(i=0;i<=n+1;i++)
{
if(sign[v][i])
{
t=dfs(i,min(map[v][i],sum));
map[v][i]-=t;
map[i][v]+=t;
sum-=t;
}
}
return s-sum;
}
int main()
{
int i,j,k,l,r,mid,ans;
scanf("%d%d%d",&K,&C,&M);
n=K+C;
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
scanf("%d",&dis[i][j]);
if(dis[i][j]==0) dis[i][j]=INF;
}
}
for(k=1;k<=n;k++)
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
if(dis[i][j]>dis[i][k]+dis[k][j])
dis[i][j]=dis[i][k]+dis[k][j];
l=0;r=10000;
while(l<r)
{
mid=(l+r)/2;
ans=0;
build(mid);
while(bfs()) ans+=dfs(0,INF);
if(ans>=C) r=mid;
else l=mid+1;
}
printf("%d\n",r);
return 0;
}

浙公网安备 33010602011771号