poj 2112 网络流

来源:互联网 发布:托福报名 知乎 编辑:程序博客网 时间:2024/05/21 11:19

题意:有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(intk=1;k<=n;k++)
    for(inti=1;i<=n;i++)
    for(intj=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];
    elseif(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));
    intque[maxn];
   level[s]=1;
    inttop=0;
   que[++top]=s;
    for(inti=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);
    intret=0;
    for(intk=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)
{
    intans=0;
   while(makelevel(s,t)) ans+=dfs(s,inf,t);
   return(ans);
}
int main()
{
    intk,c,m;
    scanf("%d %d%d",&k,&c,&m);
    intn=k+c;

   memset(a,0,sizeof(a));
    for(inti=1;i<=n;i++)
    for(intj=1;j<=n;j++)
   scanf("%d",&a[i][j]);
   floyd(n);
    intsm=1,bg=0,mid;
    for(inti=1;i<=n;i++)
    for(intj=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);
    return0;
}

原创粉丝点击