poj2112 Optimal Milking

来源:互联网 发布:ilust studio mac 编辑:程序博客网 时间:2024/05/02 18:52

poj2112 Optimal Milking 解题报告

题目原文

Time Limit: 2000MS Memory Limit: 30000KTotal Submissions: 15074 Accepted: 5386Case Time Limit: 1000MS

Description

FJ has moved his K (1 <= K <= 30) milking machines out into the cow pastures among the C (1 <= C <= 200) cows. A set of paths of various lengths runs among the cows and the milking machines. The milking machine locations are named by ID numbers 1..K; the cow locations are named by ID numbers K+1..K+C. 

Each milking point can "process" at most M (1 <= M <= 15) cows each day. 

Write a program to find an assignment for each cow to some milking machine so that the distance the furthest-walking cow travels is minimized (and, of course, the milking machines are not overutilized). At least one legal assignment is possible for all input data sets. Cows can traverse several paths on the way to their milking machine. 

Input

* Line 1: A single line with three space-separated integers: K, C, and M. 

* Lines 2.. ...: Each of these K+C lines of K+C space-separated integers describes the distances between pairs of various entities. The input forms a symmetric matrix. Line 2 tells the distances from milking machine 1 to each of the other entities; line 3 tells the distances from machine 2 to each of the other entities, and so on. Distances of entities directly connected by a path are positive integers no larger than 200. Entities not directly connected by a path have a distance of 0. The distance from an entity to itself (i.e., all numbers on the diagonal) is also given as 0. To keep the input lines of reasonable length, when K+C > 15, a row is broken into successive lines of 15 numbers and a potentially shorter line to finish up a row. Each new row begins on its own line. 

Output

A single line with a single integer that is the minimum possible total distance for the furthest walking cow. 

Sample Input

2 3 20 3 2 1 13 0 3 2 02 3 0 1 01 2 1 0 21 0 0 2 0

Sample Output

2

Source

USACO 2003 U S Open

题目大意

题目大意是说有K个挤奶机和C头奶牛,1~K节点是挤奶机,K+1~K+N节点是奶牛。每个挤奶机每天最多能让M头奶牛挤奶,问:在让所有的奶牛都能够找到挤奶机挤奶的情况下,怎样安排每头奶牛的行走路线,能够使得走的路最多的奶牛走的路最少,求出这个最小值。

解析

设一个S点和一个T点,由S点向每一个奶牛点连容量为1的边,由每个挤奶机点向T点连容量为M的边,再由每个奶牛点向它能到达的挤奶机连容量为1的边,边权为这头奶牛到这个机器的最短路(floyd预处理)。

然后二分枚举允许奶牛走的最长的路程,假设这个最长的路程为mid。并把网络流途中边权大于mid的边都删去,跑一遍最大流,如果最大流等于C,就说明所有奶牛走的路程都小于等于mid的情况下,所有奶牛都能到达挤奶机。反之,如果最大流小于C,说明所有的奶牛走的路程都小于等于mid的情况下,有些奶牛无法分配到挤奶机挤奶。

时间复杂度

假如所有边的权值都是200(题中说的上限),图又是一条链,则距离最远的两个点的距离是46000,二分的复杂度就是log46000,大约是12。每次建图的复杂度是O(CK)的,而做一次Dinic的复杂度是O((C+K)^2*CK),总的就是O( 12 * (C+K)^2 * CK ),取最大值计算,即是12*(200+30)*(200*30)=1.656*10^7,但实际上我每次mid减小就会少好多条边,最大边权也不会总是那么极端,因此实际的计算次数一定会远远小于这个值,此算法是可行的。

151520097103956412112Accepted3132K188MSG++2162B2016-02-10 19:38:38

代码

//poj2112  Optimal Milking 二分+最大流#include <cstdio>#include <cstring>#include <algorithm>#include <queue>#define maxn 500#define inf 0x3f3f3f3f#define S N+K+1#define T N+K+2using namespace std;int N, K, M, cost[maxn][maxn], head[maxn], next[maxn*maxn], c[maxn*maxn],to[maxn*maxn], tot=1, mid, f[maxn*maxn], tot_flow, deep[maxn];queue<int> q;void add(int a, int b, int v){to[++tot]=b;c[tot]=v;next[tot]=head[a];head[a]=tot;if(~tot&1)add(b,a,0);}void input(){int i, j;for(i=1;i<=N+K;i++)for(j=1;j<=N+K;j++){scanf("%d",&cost[i][j]);if(cost[i][j]==0&&i!=j)cost[i][j]=inf;}}void floyd(){int i, j, k;for(k=1;k<=N+K;k++)for(i=1;i<=N+K;i++)for(j=1;j<=N+K;j++)if(cost[i][j]>cost[i][k]+cost[k][j])cost[i][j]=cost[i][k]+cost[j][k];}void setmap(){int i, j;memset(head,0,sizeof(head));tot=1;memset(next,0,sizeof(next));for(i=1;i<=N;i++)add(S,K+i,1);for(i=1;i<=K;i++)add(i,T,M);for(i=1;i<=N;i++)for(j=1;j<=K;j++)if(cost[K+i][j]<=mid)add(K+i,j,cost[K+i][j]);}bool BFS(){int p, x;memset(deep,-1,sizeof(deep)); q.push(S);deep[S]=0;while(!q.empty()){x=q.front();q.pop();for(p=head[x];p;p=next[p])if(deep[ to[p] ]==-1 && c[p]-f[p])deep[to[p]]=deep[x]+1,q.push(to[p]);}return deep[T]!=-1;}int dfs(const int x, const int flow){int p, t;if(x==T)return flow;for(p=head[x];p;p=next[p])if( deep[to[p]]==deep[x]+1 && c[p]-f[p] && (t=dfs(to[p],min(flow,c[p]-f[p]))) ){f[p]+=t,f[p^1]-=t;return t;}return 0;}bool check(){int i, j, t;setmap();tot_flow=0;memset(f,0,sizeof(f));while(BFS())while(t=dfs(S,0x7fffffff))tot_flow+=t;return tot_flow==N;}int main(){int i, j, maxx, l, r;while(scanf("%d%d%d",&K,&N,&M)!=EOF){input();floyd();maxx=-inf;for(i=1;i<=N+K;i++) for(j=1;j<=N+K;j++)maxx=max(maxx,cost[i][j]);l=1,r=maxx,mid=(l+r)>>1;while(l<r){if(check())r=mid;else l=mid+1;mid=(l+r)>>1;}printf("%d\n",r);}return 0;}


0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 开车撞伤无证驾驶人怎么办 开车把人撞伤了只买交强险怎么办 开车撞伤人赔不起怎么办 如果车撞死人了怎么办 给车撞了跑了怎么办 开车把人撞死了怎么办 开车把人蹭了怎么办 驾照被扣54分怎么办? 驾照被扣了12分怎么办 驾驶证丢失后被扣分怎么办 驾照扣了三十分怎么办 一次被扣了12分怎么办 驾照被扣35分后怎么办 我驾驶证扣了6分怎么办 c1驾照被扣6分怎么办 被扣了6分怎么办 今年扣了6分怎么办 驾照分不够扣了怎么办 被扣6分怎么办罚款15 驾照分数扣36分怎么办 驾照12分不够扣怎么办 驾照b证扣分了怎么办 违章18分不够扣怎么办 b2驾驶证扣11分怎么办 驾照一共扣30分怎么办 驾照扣了100分怎么办 驾照扣40多分怎么办 驾照被扣69分怎么办 驾照被扣200多分怎么办 b2驾照扣了分怎么办 驾驶证在外地被冒用怎么办 身份证被冒用办驾照怎么办 外国人在中国境内死了怎么办 台风来临时航船应该怎么办 越南攻占太平岛台湾怎么办 厨房下水pvc管三通漏水怎么办 pvc下水管道接口漏水怎么办 马航机场转机行李怎么办 习惯了光脚开车怎么办 遇到暴恐分子时该怎么办视频 中国人在菲律宾失踪了怎么办