poj2112 最大流
我用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 最大流的更多相关文章
- poj2112 最大流+floyd+二分
题意:给一堆点,一部分是牛,一部分是机器,每头牛必须要走到一个机器,每个点之间有距离,要求每头牛都能找得到一台机器(机器有最大容量)的情况下,走的最远的牛距离最小 题解:二分答案,小于该距离的边才能加 ...
- POJ2112 Optimal Milking —— 二分图多重匹配/最大流 + 二分
题目链接:https://vjudge.net/problem/POJ-2112 Optimal Milking Time Limit: 2000MS Memory Limit: 30000K T ...
- POJ-2112 Optimal Milking(floyd+最大流+二分)
题目大意: 有k个挤奶器,在牧场里有c头奶牛,每个挤奶器可以满足m个奶牛,奶牛和挤奶器都可以看成是实体,现在给出两个实体之间的距离,如果没有路径相连,则为0,现在问你在所有方案里面,这c头奶牛需要走的 ...
- POJ2112 Optimal Milking 【最大流+二分】
Optimal Milking Time Limit: 2000MS Memory Limit: 30000K Total Submissions: 12482 Accepted: 4508 ...
- poj2112 二分最大流+Floyd
题意: 一个农场主有一些奶牛,和一些机器,每台机器有自己的服务上限,就是一天最多能给多少头奶牛挤奶,给你任意两点的距离,问你让所有的奶牛都被挤奶时,奶牛于机器最远距离的最近是多少. 思路: ...
- POJ2112 Optimal Milking(最大流)
先Floyd求牛到机器最短距离,然后二分枚举最长的边. #include<cstdio> #include<cstring> #include<queue> #in ...
- poj2112(网络流-最大流+二分)
题意:给你k个挤奶器,c头牛,每个挤奶器能放m头牛,问你奶牛需要走的最大距离最小是多少: 解题思路:因为最大距离最小,也就是求最小的距离满足所有牛都能到,所以我们先用floyd跑最短路,把所有点之间的 ...
- poj2112 二分+floyd+多源多汇最大流
/*此题不错,大致题意:c头牛去k个机器处喝奶,每个喝奶处最多容纳M头牛,求所有牛中走的最长路的 那头牛,使该最长路最小.思路:最大最小问题,第一灵感:二分答案check之.对于使最长路最短, 用fo ...
- [Poj2112][USACO2003 US OPEN] Optimal Milking [网络流,最大流][Dinic+当前弧优化]
题意:有K个挤奶机编号1~K,有C只奶牛编号(K+1)~(C+K),每个挤奶机之多能挤M头牛,现在让奶牛走到挤奶机处,求奶牛所走的最长的一条边至少是多少. 题解:从起点向挤奶机连边,容量为M,从挤奶机 ...
随机推荐
- [转]C#截获本机数据包方法实例
本文向大家介绍Windows Sockets的一些关于用C#实现的原始套接字(Raw Socket)的编程,以及在此基础上实现的网络封包监视技术.同Winsock1相比,Winsock2最明显的就是支 ...
- 文件内容操作命令 cat、more、less、head、tail、wc、grep 命令详情
文件内容操作命令 cat.more.less.head.tail.wc.grep 命令详情 1) cat命令 用途:显示出文件的全部内容 格式:cat 目标文件 例: ...
- react-native连接华为真机
android studio的设置:下载google USB Driver 手机部分1.找到手机开发者模式 设置->系统->关于手机->版本号(多次点击出现开发者模式) 提示你已在开 ...
- 唱吧基于 MaxCompute 的大数据之路
使用 MaxCompute之前,唱吧使用自建体系来存储处理各端收集来的日志数据,包括请求访问记录.埋点数据.服务器业务数据等.初期这套基于开源组件的体系有力支撑了数据统计.业务报表.风控等业务需求.但 ...
- MAC中已有的虚拟环境在pycharm 中进行调用
首先确定虚拟环境的路径: 打开工作环境配置文件,找到工作目录: 在pycharm中解释器中找到工作目录中对应的虚拟环境进行配置就可以了
- Thinkphp M方法出错,D方法却可以
错误回顾: M('Local')->find(); //报错 //错误信息:Table 'test.local' doesn't exist [ SQL语句 ] : SHOW COLUMNS F ...
- NLog系列之NLong.config变量配置篇
$ {cached} - 将缓存应用于另一个布局输出. $ {db-null} - 为数据库渲染DbNull $ {exception} - 通过调用Logger方法之一提供的异常信息 $ {lev ...
- const属性与容器元素排序
给容器里元素排序时,会破坏容器的const的属性:因此当你在一个函数传参的时候如果使用的是const T&:那么你在调用qt的qsort给容器排序的时候可能会遭遇一些看不懂的BUG提示 类似: ...
- JQ效果 透明图片覆盖动画
效果图呈上 先说思路 1,一个固定的框架,有两张图片,一张是狗狗的,一张是练习方式,想把做好的练习方式隐藏 2,效果上想要从下面滑动出来,所以透明框定位在下面 3,整理需要的东西,缓慢升起需要动画效果 ...
- PHP之文件目录基础操作方法
1.文件的属性信息获取 首先文件具有类型,在linux下边,有block(块设备,如磁盘分区.CD-ROM).char(以字符为输入的设备,如键盘.打印机).dir(目录类型,目录也是文件的一种).f ...