caioj.cn 1119網路流入門5:牛擠奶
阿新 • • 發佈:2018-11-25
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; }