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,从挤奶机 ...
随机推荐
- python intern(字符串驻留机制)
python 中为了提高字符串的使用用效率和节约内存,对于由 字母.数字.下划线组成的标识符采用了 intern 机制,即对于短字符串,将其赋值给多个对象时,内存中只有一个副本,多个对象共享这个副本. ...
- BTC功能类
<?php/*EasyBitcoin-PHP A simple class for making calls to Bitcoin's API using PHP.https://github. ...
- Eclipse:Eclipse所有发布版本的下载地址
官方镜像:http://eclipse.mirror.rafal.ca/technology/epp/downloads/release/ 国内镜像:http://mirrors.neusoft.ed ...
- 2019阿里云开年Hi购季必抢!爆爆爆爆爆爆爆款清单来了!
摘要: 鸡冻人心的三月开年Hi购季来了,根本不知道该买哪款?这次就给大家列一波口碑爆款! 鸡冻人心的三月开年Hi购季来了 个个摩拳擦掌 为了算清楚能省多少钱 颓废多年的数学水平 仿佛在这个节日回到了高 ...
- JS 重载页面,本地刷新,返回上一页
JS 重载页面,本地刷新,返回上一页 : <a href="javascript:history.go(-1)">返回上一页</a> <a href= ...
- php用mysql方式连接数据库出现Deprecated报错
以上是用php5.5 连接mysql数据库时报的错. 于是我用php5.4 连接正常没有报错. 这与mysql版本无关系,php 5.x版本,如5.2.5.3.5.4.5.5,怕跟不上时代,新的服务器 ...
- jeecms9自定义标签以及使用新创建的数据库表
转载 https://blog.csdn.net/nice_meng/article/details/89179089 本系统使用的是jeecmsv9版本,收集网上知识后,进行个人汇总 首先,自己创建 ...
- socker TCP UDP BIO NIO
BIO: Java 1.4 以前只有之中方式. bio:阻塞式IO, 一个 socker 连接占用一个 线程.如果 IO 阻塞,会在传输速度限制,这个线程也会一直等待在这里,等待从socker 的 ...
- 详谈Windows消息循环机制
一直对windows消息循环不太清楚,今天做个详细的总结,有说错的地方,请务必指出. 用VS2017新建一个win32 Application的默认代码如下: 程序入口 ...
- CentOS 7安装与配置JDK8
1.检查是否安装过JDK 2.下载安装包并上传服务器 3.安装JDK rpm -ivh jdk-8u131-linux-x64.rpm 4.查看是否安装正常 java -version 5.配置环境变 ...