我用Dinic写的。G++ 1800ms 很慢,c++直接超时。优化后的 141ms,很快!

对于此题,建图方法很巧妙,通常想到求距离,那就会朝距离的方向建图,但是这题根据牛个数来建图,然后二分距离。

  先求出任意点之间的最短距离。对于挤奶器,牛,很明显的分为2部分。挤奶器的牛来自牛这部分。先另外设源点和汇点。对于牛部分,都与源点相连,容量为1。然后二分

距离,对于挤奶器和牛之间的容量,如果挤奶器和牛之间的距离小于或等于二分的距离,那么此路可以通过牛。然后挤奶器与汇点之间的容量为m值。这样图就建完了。然后Dinic

求最大流(此时最大流的值表示牛的个数),如果此时最大流的值>=c,即满足牛的个数,那这个距离是可以的,然后继续二分,知道得到结果。

#include<stdio.h>
#include<string.h>
#include<queue>
#define maxn 300
#define INF 99999999
using namespace std;
int map[maxn][maxn],dis[maxn][maxn],vis[maxn];
int k,c,m;
int min(int x,int y)
{
return x<y?x:y;
}
void floyd(int n)
{
int i,j,t;
for(t=;t<=n;t++)
{
for(i=;i<=n;i++)
{
for(j=;j<=n;j++)
{
if(dis[i][j]>dis[i][t]+dis[t][j])
dis[i][j]=dis[i][t]+dis[t][j];
}
}
}
}
void makemap(int maxval,int n)
{
int i,j;
memset(map,,sizeof(map));
for(i=;i<=k;i++)
map[i][n+]=m;
for(i=k+;i<=n;i++)
map[][i]=;
for(i=k+;i<=n;i++)
{
for(j=;j<=k;j++)
{
if(dis[i][j]<=maxval)
map[i][j]=;
}
}
}
int BFS(int n)
{
int i,j;
queue<int>q;
memset(vis,-,sizeof(vis));
vis[]=;
q.push();
while(!q.empty())
{
int t=q.front();
q.pop();
for(i=;i<=n+;i++)
{
if(vis[i]<&&map[t][i])
{
q.push(i);
vis[i]=vis[t]+;
}
}
}
if(vis[n+]>)
return ;
return ;
}
int dfs(int u,int low,int n)
{
int i,j,a;
if(u==n)
return low;
for(i=;i<=n;i++)
{
if(vis[i]==vis[u]+&&map[u][i])
{
a=dfs(i,min(low,map[u][i]),n);
if(!a)continue;
map[u][i]-=a;
map[i][u]+=a;
return a;
}
}
return ;
}
int main()
{
int i,j,n;
while(scanf("%d%d%d",&k,&c,&m)!=EOF)
{
n=k+c;
for(i=;i<=k+c;i++)
{
for(j=;j<=k+c;j++)
{
scanf("%d",&dis[i][j]);
if(dis[i][j]==)//不连通给予无穷,防止floyd出现问题
dis[i][j]=INF;
}
}
floyd(n); /*for(i=1;i<=k+c;i++)
{
for(j=1;j<=k+c;j++)
{
printf("%d ",dis[i][j]);
}
printf("\n");
}*/ int L=,R=;
int ans=;
int rt=;
while(L<=R)//二分答案
{
rt=;
int mid=(L+R)/;
makemap(mid,n);//根据二分的值建图
while(BFS(n))
{
int fa=dfs(,INF,n+);
if(!fa) break;;
rt+=fa;
}
if(rt>=c)
{
R=mid-;
ans=mid;
}
else
{
L=mid+;
}
}
printf("%d\n",ans);
}
}

优化后:

#include<stdio.h>
#include<string.h>
#include<queue>
#define maxn 300
#define INF 99999999
using namespace std;
int map[maxn][maxn],dis[maxn][maxn],vis[maxn];
int k,c,m;
int min(int x,int y)
{
return x<y?x:y;
}
void floyd(int n)
{
int i,j,t;
for(t=;t<=n;t++)
{
for(i=;i<=n;i++)
{
for(j=;j<=n;j++)
{
if(dis[i][j]>dis[i][t]+dis[t][j])
dis[i][j]=dis[i][t]+dis[t][j];
}
}
}
}
void makemap(int maxval,int n)
{
int i,j;
memset(map,,sizeof(map));
for(i=;i<=k;i++)
map[i][n+]=m;
for(i=k+;i<=n;i++)
map[][i]=;
for(i=k+;i<=n;i++)
{
for(j=;j<=k;j++)
{
if(dis[i][j]<=maxval)
map[i][j]=;
}
}
}
int BFS(int n)
{
int i,j;
queue<int>q;
memset(vis,-,sizeof(vis));
vis[]=;
q.push();
while(!q.empty())
{
int t=q.front();
q.pop();
for(i=;i<=n+;i++)
{
if(vis[i]<&&map[t][i])
{
q.push(i);
vis[i]=vis[t]+;
}
}
}
if(vis[n+]>)
return ;
return ;
}
int dfs(int u,int low,int n)
{
int i,j,a,used=;
if(u==n)
return low;
for(i=;i<=n&&used<low;i++)
{
if(vis[i]==vis[u]+&&map[u][i])
{
a=dfs(i,min(low-used,map[u][i]),n);//多路增广
if(!a)continue;
map[u][i]-=a;
map[i][u]+=a;
used+=a;
}
}
if(!used)
vis[u]=-;
return used;
}
int main()
{
int i,j,n;
while(scanf("%d%d%d",&k,&c,&m)!=EOF)
{
n=k+c;
for(i=;i<=k+c;i++)
{
for(j=;j<=k+c;j++)
{
scanf("%d",&dis[i][j]);
if(dis[i][j]==)//不连通给予无穷,防止floyd出现问题
dis[i][j]=INF;
}
}
floyd(n); /*for(i=1;i<=k+c;i++)
{
for(j=1;j<=k+c;j++)
{
printf("%d ",dis[i][j]);
}
printf("\n");
}*/ int L=,R=;
int ans=;
int rt=;
while(L<=R)//二分答案
{
rt=;
int mid=(L+R)/;
makemap(mid,n);//根据二分的值建图
while(BFS(n))
{
int fa=dfs(,INF,n+);
if(!fa) break;;
rt+=fa;
}
if(rt>=c)
{
R=mid-;
ans=mid;
}
else
{
L=mid+;
}
}
printf("%d\n",ans);
}
}

poj2112 最大流的更多相关文章

  1. poj2112 最大流+floyd+二分

    题意:给一堆点,一部分是牛,一部分是机器,每头牛必须要走到一个机器,每个点之间有距离,要求每头牛都能找得到一台机器(机器有最大容量)的情况下,走的最远的牛距离最小 题解:二分答案,小于该距离的边才能加 ...

  2. POJ2112 Optimal Milking —— 二分图多重匹配/最大流 + 二分

    题目链接:https://vjudge.net/problem/POJ-2112 Optimal Milking Time Limit: 2000MS   Memory Limit: 30000K T ...

  3. POJ-2112 Optimal Milking(floyd+最大流+二分)

    题目大意: 有k个挤奶器,在牧场里有c头奶牛,每个挤奶器可以满足m个奶牛,奶牛和挤奶器都可以看成是实体,现在给出两个实体之间的距离,如果没有路径相连,则为0,现在问你在所有方案里面,这c头奶牛需要走的 ...

  4. POJ2112 Optimal Milking 【最大流+二分】

    Optimal Milking Time Limit: 2000MS   Memory Limit: 30000K Total Submissions: 12482   Accepted: 4508 ...

  5. poj2112 二分最大流+Floyd

    题意:      一个农场主有一些奶牛,和一些机器,每台机器有自己的服务上限,就是一天最多能给多少头奶牛挤奶,给你任意两点的距离,问你让所有的奶牛都被挤奶时,奶牛于机器最远距离的最近是多少. 思路: ...

  6. POJ2112 Optimal Milking(最大流)

    先Floyd求牛到机器最短距离,然后二分枚举最长的边. #include<cstdio> #include<cstring> #include<queue> #in ...

  7. poj2112(网络流-最大流+二分)

    题意:给你k个挤奶器,c头牛,每个挤奶器能放m头牛,问你奶牛需要走的最大距离最小是多少: 解题思路:因为最大距离最小,也就是求最小的距离满足所有牛都能到,所以我们先用floyd跑最短路,把所有点之间的 ...

  8. poj2112 二分+floyd+多源多汇最大流

    /*此题不错,大致题意:c头牛去k个机器处喝奶,每个喝奶处最多容纳M头牛,求所有牛中走的最长路的 那头牛,使该最长路最小.思路:最大最小问题,第一灵感:二分答案check之.对于使最长路最短, 用fo ...

  9. [Poj2112][USACO2003 US OPEN] Optimal Milking [网络流,最大流][Dinic+当前弧优化]

    题意:有K个挤奶机编号1~K,有C只奶牛编号(K+1)~(C+K),每个挤奶机之多能挤M头牛,现在让奶牛走到挤奶机处,求奶牛所走的最长的一条边至少是多少. 题解:从起点向挤奶机连边,容量为M,从挤奶机 ...

随机推荐

  1. KOA 学习(六)superAgent

    原文地址 http://www.2cto.com/kf/201611/569080.html 基本请求 初始化一个请求可以通过调用request模块中适当的方法,然后使用.end()来发送请求,例如一 ...

  2. spring-注解配置-junit整合测试-aop

    1 使用注解配置spring 1.1 步骤 导包4+2+spring-aop 1.为主配置文件引入新的命名空间(约束) 2.开启使用注解代理配置文件 3.在类中使用注解完成配置 1.2 将对象注册到容 ...

  3. 使用tomcat脚本开启服务

    参考:https://www.cnblogs.com/fps2tao/p/8488596.html 1.编写tomcat脚本 在/etc/init.d/目录下创建tomcat服务脚本文件 cd  /e ...

  4. 实例详解TOP命令

    Linux中的top命令显示系统上正在运行的进程.它是系统管理员最重要的工具之一.被广泛用于监视服务器的负载.在本篇中,我们会探索top命令的细节.top命令是一个交互命令.在运行top的时候还可以运 ...

  5. maven-home

    E:/Soft/Maven/apache-maven-3.3.3 E:\Soft\Maven\apache-maven-3.3.3\conf\settings.xml E:\DellWork\Mave ...

  6. Shell 常用特性

       管道(|) 管道 (|): 将一个命令的输出作为另外一个命令的输入.   管道同样可以在标准输入输出和标准错误输出间做代替工作,这样一来,可以将某一个程序的输出送到另一个程序的输入,其语法如下: ...

  7. Vue.之.路由跳转

    Vue.之.路由跳转 在进行项目开发的过程中,需要使用路由进行跳转.如下: // 不带有参数,在页面上跳转到别的页面 1. this.$router.push('/login/init');  // ...

  8. 1、jxl导入/导出excel案例,黏贴即可运行

    package junit.test; import java.io.File; import java.io.IOException; import java.util.ArrayList; imp ...

  9. Java 8最快的垃圾收集器是什么?

    OpenJDK 8 有多种 GC(Garbage Collector)算法,如 Parallel GC.CMS 和 G1.哪一个才是最快的呢?如果在 Java 9 中将 Java 8 默认的 GC 从 ...

  10. Leetcode34.Find First and Last Position of Element in Sorted Array在排序数组中查找元素的位置

    给定一个按照升序排列的整数数组 nums,和一个目标值 target.找出给定目标值在数组中的开始位置和结束位置. 你的算法时间复杂度必须是 O(log n) 级别. 如果数组中不存在目标值,返回 [ ...