poj2112(网络流-最大流+二分)

时间:2023-03-10 01:26:50
poj2112(网络流-最大流+二分)

题意:给你k个挤奶器,c头牛,每个挤奶器能放m头牛,问你奶牛需要走的最大距离最小是多少;

解题思路:因为最大距离最小,也就是求最小的距离满足所有牛都能到,所以我们先用floyd跑最短路,把所有点之间的距离算出来后再,对答案进行二分:牛和挤奶器的距离<=二分值的可以连一条边,容量为1;

然后源点和奶牛连一条容量为1的边,挤奶器和汇点连一条容量为m的边,所以二分只是为了看奶牛是否能到达某个挤奶器;

代码:

#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
#include<cstdio>
#define maxn 100500
#define inf 0x3f3f3f3f
using namespace std;
struct Edge
{
int next;
int to;
int w;
int fa;
}edge[maxn];
int head[maxn];
int x,y;
int dist[505][505];
int cnt;
int n,m,Start,End;
int k,c;
int depth[maxn];
void floyd()
{
for(int l=1;l<=c+k;l++)
{
for(int i=1;i<=c+k;i++)
{
for(int j=1;j<=c+k;j++)
{
if(dist[i][j]>dist[i][l]+dist[l][j])
dist[i][j]=dist[i][l]+dist[l][j];
}
}
}
}
void add(int u,int v,int w)
{
edge[cnt].next=head[u];edge[cnt].to=v;
edge[cnt].fa=u;edge[cnt].w=w;head[u]=cnt++;
edge[cnt].next=head[v];edge[cnt].w=0;
edge[cnt].to=u;edge[cnt].fa=v;head[v]=cnt++;
}
bool bfs()
{
memset(depth,0,sizeof(depth));
queue<int>q;
q.push(Start);
depth[Start]=1;
while(!q.empty())
{
int u=q.front();
q.pop();
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].to;
if(depth[v]||edge[i].w<=0)
continue;
depth[v]=depth[u]+1;
q.push(v);
}
}
return depth[End];
}
int dfs(int u,int maxflow)
{
if(u==End)
return maxflow;
int add=0;
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].to;
if(depth[v]!=depth[u]+1)
continue;
if(edge[i].w==0)
continue;
int tempflow=dfs(v,min(edge[i].w,maxflow-add));
edge[i].w-=tempflow;
edge[i^1].w+=tempflow;
add+=tempflow;
}
return add;
}
int dinic()
{
int ans=0;
while(bfs())
{
ans+=dfs(Start,inf);
}
return ans;
}
void buildmap(int value)
{
memset(head ,-1,sizeof(head));
cnt=0;
for(int i=k+1;i<=k+c;i++)
{
add(0,i,1);
}
for(int i=k+1;i<=k+c;i++)
{
for(int j=1;j<=k;j++)
{
if(dist[i][j]<=value)
{
add(i,j,1);
// cout<<i<<" "<<j<<endl;
}
}
}
for(int i=1;i<=k;i++)
{
add(i,k+c+1,m);
}
}
int main()
{
scanf("%d%d%d",&k,&c,&m);
Start=0;End=k+c+1;
for(int i=1;i<=k+c;i++)
{
for(int j=1;j<=k+c;j++)
{
scanf("%d",&dist[i][j]);
if(dist[i][j]==0)
dist[i][j]=inf;
}
}
floyd();
int l=0,r=10000;
while(l<r)
{
int mid=(l+r)/2;
buildmap(mid);
int xx=dinic();
if(xx>=c)
{
r=mid;
}
else
{
l=mid+1;
}
}
printf("%d\n",r);
}