您的位置:首页 > 理论基础 > 计算机网络

poj 2112 网络流

2013-04-14 19:37 357 查看
题意:有K台挤奶机(编号1~K),C头奶牛(编号K+1~K+C),给出各点之间距离。现在要让C头奶牛到挤奶机去挤奶,每台挤奶机只能处理M头奶牛,求使所走路程最远的奶牛的路程最短的方案。

构图:先Floyd求所有点对之间最短路,二分最短长度,若奶牛与挤奶机之间的距离大于mid则不连边,否则连容量为1的边。源向奶牛连容量1的边,机器向汇连容量m的边,用最大流判可行性。

#include <iostream>

#include<stdio.h>

#include<string.h>

const int maxn=1001;

const int inf=1<<30;

using namespace std;

int a[maxn][maxn],e[maxn][maxn];

int floyd(int n)

{

for(int
k=1;k<=n;k++)

for(int
i=1;i<=n;i++)

for(int
j=1;j<=n;j++)

if(a[i][k]&&a[k][j]&&a[i][k]+a[k][j]<a[i][j])

a[i][j]=a[i][k]+a[k][j];

else
if(a[i][k]&&a[k][j]&&a[i][j]==0)

a[i][j]=a[i][k]+a[k][j];

}

int level[maxn];

int makelevel(int s,int t)

{

memset(level,0,sizeof(level));

int
que[maxn];

level[s]=1;

int
top=0;

que[++top]=s;

for(int
i=1;i<=top;i++)

{

int u=que[i];

if(u==t) return(1);

for(int k=1;k<=t;k++)

if(!level[k]&&e[u][k])

{

que[++top]=k;

level[k]=level[u]+1;

}

}

return(0);

}

int dfs(int now,int maxf,int t)

{

if(now==t)
return(maxf);

int
ret=0;

for(int
k=1;k<=t;k++)

if(e[now][k]&&level[k]==level[now]+1)

{

int f=dfs(k,min(maxf-ret,e[now][k]),t);

e[now][k]-=f;

e[k][now]+=f;

ret+=f;

if(ret==maxf) return(ret);

}

return(ret);

}

int dinic(int s,int t)

{

int
ans=0;

while(makelevel(s,t)) ans+=dfs(s,inf,t);

return(ans);

}

int main()

{

int
k,c,m;

scanf("%d %d
%d",&k,&c,&m);

int
n=k+c;

memset(a,0,sizeof(a));

for(int
i=1;i<=n;i++)

for(int
j=1;j<=n;j++)

scanf("%d",&a[i][j]);

floyd(n);

int
sm=1,bg=0,mid;

for(int
i=1;i<=n;i++)

for(int
j=1;j<=n;j++)

if(a[i][j]>bg) bg=a[i][j];

mid=(sm+bg)/2;

while(sm!=bg)

{

memset(e,0,sizeof(e));

for(int i=1;i<=k;i++)

e[i][c+k+2]=m;

for(int i=k+1;i<=k+c;i++)

e[c+k+1][i]=1;

for(int i=k+1;i<=n;i++)

for(int j=1;j<=k;j++)

if(a[i][j]<=mid&&a[i][j])

e[i][j]=1;

if(dinic(c+k+1,c+k+2)==c)

{

bg=mid;

mid=(sm+bg)/2;

}

else

{

sm=mid+1;

mid=(sm+bg)/2;

}

//
printf("%d %d\n",sm,bg);

}

printf("%d\n",sm);

return
0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: