您的位置:首页 > 其它

POJ 2112 二分+最大流

2013-01-07 00:38 393 查看
题意:

有k个牛奶机跟c头牛。他们之间有路相连,农民想让每个牛能到其中一个牛奶机,又想让走路最远的牛走得最小。

题解:

求最大值最小,不出意外就是二分了

由于要限制总的路径长度,就不能对每条边限制了,于是先floyd求最短路,再二分最长路即可~

不连大于二分值的路径,连小于等于二分值的路径,做最大流就好了~

View Code

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>

#define N 250
#define M 600000
#define INF 100000

using namespace std;

int map

,m,c,k,l,r,S,T,head
,next[M],to[M],len[M],q[M<<4],cnt,layer
,mid,dis
,num;

inline void add(int u,int v,int w)
{
to[cnt]=v; len[cnt]=w; next[cnt]=head[u]; head[u]=cnt++;
to[cnt]=u; len[cnt]=0; next[cnt]=head[v]; head[v]=cnt++;
}

void read()
{
num=0;
for(int i=1;i<=k+c;i++)
for(int j=1;j<=k+c;j++)
{
scanf("%d",&map[i][j]);
if(map[i][j]==0) map[i][j]=INF;
}
for(int p=1;p<=k+c;p++)//floyd处理最短路
for(int i=1;i<=k+c;i++)
for(int j=1;j<=k+c;j++)
if(map[i][p]<INF&&map[p][j]<INF)
map[i][j]=min(map[i][p]+map[p][j],map[i][j]);
}

void create()
{
S=0;T=k+c+1;
memset(head,-1,sizeof head);
cnt=0;
for(int i=1;i<=k;i++) add(S,i,m);
for(int i=k+1;i<=k+c;i++) add(i,T,1);
for(int i=1;i<=k;i++)
for(int j=k+1;j<=k+c;j++)
if(map[i][j]<=mid) add(i,j,1);
}

bool bfs()
{
memset(layer,-1,sizeof layer);
int h=1,t=2,sta;
layer[S]=0; q[1]=S;
while(h<t)
{
sta=q[h++];
for(int i=head[sta];~i;i=next[i])
if(len[i]>0&&layer[to[i]]<0)
{
layer[to[i]]=layer[sta]+1;
q[t++]=to[i];
}
}
return layer[T]!=-1;
}

int find(int u,int cur_flow)
{
int tmp=0,result=0;
if(u==T) return cur_flow;
for(int i=head[u];~i&&result<cur_flow;i=next[i])
if(len[i]>0&&layer[to[i]]==layer[u]+1)
{
tmp=find(to[i],min(cur_flow-result,len[i]));
len[i]-=tmp; len[i^1]+=tmp; result+=tmp;
}
if(!result) layer[u]=-1;
return result;
}

int dinic()
{
create();
int ans=0;
while(bfs()) ans+=find(S,INF);
return ans;
}

void go()
{
int ans;
l=0,r=100000;
while(l<=r)
{
mid=(l+r)>>1;
if(dinic()>=c) r=mid-1;
else l=mid+1;
}
printf("%d\n",l);
}

int  main()
{
scanf("%d%d%d",&k,&c,&m);
read();
go();
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: