1. 程式人生 > >caioj.cn 1119網路流入門5:牛擠奶

caioj.cn 1119網路流入門5:牛擠奶

1119: [視訊]網路流入門5:牛擠奶

時間限制: 1 Sec  記憶體限制: 128 MB
提交: 74  解決: 26
[ 提交][ 狀態][ 討論版]

題目描述

  

【題目描述】

FJ把K個擠奶機搬進了住著C頭奶牛的牧場。擠奶機的編號為1~K,奶牛的編號為K+1~~K+C。每頭奶牛到每臺擠奶機距離不同。每臺擠奶機每天最多服務M頭奶牛。求一種分配方案, 使得走得最遠的奶牛走過的距離最小化。輸出此距離.

【輸入格式】

資料第1行是3個整數K,C,M(1≤K≤30)(1≤C≤200)(1≤M≤15)

接下來是一個(K+C)×(K+C)的距離矩陣。矩陣元素為正並不超200。距離為0表示兩個點之間無邊存在。

【輸出格式】

輸出一個整數,即走得最遠的奶牛走過的距離的最小化值。

【樣例輸入】

2 3 2

0 3 2 1 1

3 0 3 2 0

2 3 0 1 0

1 2 1 0 2

1 0 0 2 0

【樣例輸出】

2

這一道題還是和前一道題一樣,設定原點和匯點,用floyd查詢最短路徑,二分查詢中用網路流判斷

思路就不說了

#include<cstdio>
#include<cstring>
using namespace std;
struct node
{
    int x,y,c,next,other;
}a[110000];
int len,last[110000],st,ed;
void ins(int x,int y,int c)
{
    int k1,k2;
    len++;k1=len;
    a[len].x=x;a[len].y=y;a[len].c=c;
    a[len].next=last[x];last[x]=len;
    len++;k2=len;
    a[len].x=y;a[len].y=x;a[len].c=0;
    a[len].next=last[y];last[y]=len;
    a[k1].other=k2;
    a[k2].other=k1;
}
int list[410],head,tail,h[410];
bool bt_h()
{
    memset(h,0,sizeof(h));h[st]=1;
    list[1]=st;head=1;tail=2;
    while(head!=tail)
    {
        int x=list[head];
        for(int k=last[x];k;k=a[k].next)
        {
            int y=a[k].y;
            if(a[k].c>0 && h[y]==0)
            {
                h[y]=h[x]+1;
                list[tail++]=y;
            }
        }
        head++;
    }
    if(h[ed]>0)return true;
    else return false;
}
int mymin(int x,int y)
{
    return x<y?x:y;
}
int findflow(int x,int f)
{
    if(x==ed)return f;
    int s=0,t;
    for(int k=last[x];k;k=a[k].next)
    {
        int y=a[k].y;
        if(a[k].c>0 && h[y]==(h[x]+1) && s<f)
        {
            s+=(t=findflow(y,mymin(a[k].c,f-s)));
            a[k].c-=t;
            a[a[k].other].c+=t;
        }
    }
    if(s==0)h[x]=0;
    return s;
}
int K,C,M;
int map[310][310];
int check(int x)
{
	len=0;memset(last,0,sizeof(last));
	for(int i=K+1;i<=K+C;i++)
	{
		for(int j=1;j<=K;j++)
		{
			if(map[i][j]<=x) 
				ins(i,j,1);
		}
	}
	for(int i=1;i<=K;i++)
	{
		ins(i,ed,M); 
	}
	for(int i=K+1;i<=K+C;i++)
	{
		ins(st,i,1);
	}
	int s=0;
	while(bt_h()==true) s=s+findflow(st,999999999);
	return s;
}
int main()
{
    scanf("%d%d%d",&K,&C,&M);
    st=K+C+1;ed=st+1;
    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]=999999999;
    	}
    }
    for(int k=1;k<=K+C;k++)
    	for(int i=1;i<=K+C;i++) if(i!=k)
    		for(int j=1;j<=K+C;j++) if(i!=j && j!=k)
    			if(map[i][j]>map[i][k]+map[k][j])
    			 	map[i][j]=map[i][k]+map[k][j];
	int l,r,mid,ans;
	l=1;r=200*230;
	while(l<=r)
	{
		mid=(l+r)/2;
		if(check(mid)==C)
		{
			r=mid-1;ans=mid;
		}
		else
		{
			l=mid+1;
		}
	}
	printf("%d\n",ans);
	return 0;
}