题目:

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3496

大概意思:给你一个网络,有源汇,在保证最大流的情况下求下面两个问题答案

1.所有边中流量最大的边流量最小

2.所有边中流量最小的边流量最大


题解:

De了一下午啊啊,之前学的上下界网络流有问题!

对于问题一,我们二分最大流量,每次建图跑最大流,看是不是和之前一样即可

对于问题二,我们同样二分答案lim,这样每条边满足流量限制w[i]∈[lim,c[i]]

这样建图跑有源汇最大流即可.

下面是坑点

之前写的有源汇最大流都是先跑可行流然后把超级源和超级汇删掉再跑,答案还得加加减减,但是就是Wa

后来发现其实并没有那么难,在可行流的残余网络直接再跑一边最大流就是答案

感性证明如下:

因为如果可行的话超级源的所有出边都满流,这样算最大流的时候只会算到t->s的反边上,又因为原来的可行流就在这条边上,这样直接就能算出答案

别忘了输出答案*p

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
typedef long long ll;
#define N 505
#define M 400005
#define INF 0x3f3f3f3f
using namespace std;
ll Case,n,m,t,s,P,ans1,ans2,S,T,ecnt,Maxflow,l,r,u[M],v[M],c[M],mid,Maxc,lim;
ll head[N],lev[N],cur[N],du[N];
queue <ll> q;
struct adj
{
ll nxt,v,w;
} e[M];
ll read()
{
ll ret=,neg=;
char j=getchar();
for (; j>'' || j<''; j=getchar())
if (j=='-') neg=-;
for (; j>='' && j<=''; j=getchar())
ret=ret*+j-'';
return ret*neg;
}
void add(ll u,ll v,ll w)
{
e[++ecnt].v=v;e[ecnt].w=w;e[ecnt].nxt=head[u];head[u]=ecnt;
e[++ecnt].v=u;e[ecnt].w=;e[ecnt].nxt=head[v];head[v]=ecnt;
}
void init()
{
ecnt=;
memset(head,,sizeof(head));
}
bool Bfs()
{
while (!q.empty()) q.pop();
for (ll i=; i<=lim; i++)
cur[i]=head[i],lev[i]=-;
q.push(S),lev[S]=;
while (!q.empty())
{
ll u=q.front();
q.pop();
for (ll i=head[u],v; i; i=e[i].nxt)
if (lev[v=e[i].v]==- && e[i].w>)
{
q.push(v),lev[v]=lev[u]+;
if (v==T) return ;
}
}
return ;
}
ll Dfs(ll u,ll flow)
{
if (u==T) return flow;
ll ret=,delta;
for (ll &i=cur[u],v; i; i=e[i].nxt)
if (e[i].w> && lev[v=e[i].v]==lev[u]+)
{
delta=Dfs(v,min(e[i].w,flow-ret));
if (delta)
{
e[i].w-=delta;
e[i^].w+=delta;
ret+=delta;
if (ret==flow) break;
}
}
return ret;
}
ll getG(ll lim)
{
ll sum=,tmp=;
init();
add(t,s,INF);S=n+,T=n+;
memset(du,,sizeof(du));
for (ll i=; i<=m; i++)
if (c[i]-lim<) return -;
else add(u[i],v[i],c[i]-lim),du[u[i]]-=lim,du[v[i]]+=lim;
for (ll i=; i<=n; i++)
{
if (du[i]>) add(S,i,du[i]),sum+=du[i];
if (du[i]<) add(i,T,-du[i]);
}
while (Bfs()) tmp+=Dfs(S,INF);
if (tmp!=sum) return -;
tmp=;S=s;T=t;
while (Bfs()) tmp+=Dfs(S,INF);
return tmp;
}
int main()
{
Case=read();
while (Case--)
{
n=read(),m=read(),s=read(),t=read(),P=read();
init();
S=++s;T=++t;
Maxflow=Maxc=l=;
lim=n+;
for (ll i=; i<=m; i++)
u[i]=read(),v[i]=read(),c[i]=read(),add(++u[i],++v[i],c[i]),r=Maxc=max(Maxc,c[i]);
while (Bfs()) Maxflow+=Dfs(S,INF);
while (l<r)
{
init();
ll mid=l+r>>,tmp=;
for (ll i=; i<=m; i++) add(u[i],v[i],min(c[i],mid));
while (Bfs()) tmp+=Dfs(S,INF);
if (tmp==Maxflow) r=mid;
else l=mid+;
}
ans1=l;l=;r=Maxc;
while (l<r)
{
ll mid=l+r+>>,tmp=;
if (getG(mid)==Maxflow) l=mid;
else r=mid-;
}
ans2=l;
printf("%lld %lld\n",1ll*ans1*P,1ll*ans2*P);
}
return ;
}

ZOJ 3496 Assignment | 二分+有上下界网络流的更多相关文章

  1. [zoj] 3496 Assignment || 有源汇上下界最大流

    原题 贴个博客吧 #include<cstdio> #include<algorithm> #include<cstring> #define N 510 #def ...

  2. 【上下界网络流 二分】bzoj2406: 矩阵

    感觉考试碰到上下界网络流也还是写不来啊 Description Input 第一行两个数n.m,表示矩阵的大小. 接下来n行,每行m列,描述矩阵A. 最后一行两个数L,R. Output 第一行,输出 ...

  3. BZOJ 2406 二分+有上下界的网络流判定

    思路: 求出每行的和  sum_row 每列的和   sum_line 二分最后的答案mid S->i  流量[sum_row[i]-mid,sum_row[i]+mid] i->n+j ...

  4. ZOJ Problem Set - 3229 Shoot the Bullet 【有上下界网络流+流量输出】

    题目:problemId=3442" target="_blank">ZOJ Problem Set - 3229 Shoot the Bullet 分类:有源有汇 ...

  5. 【有上下界网络流】【ZOJ】2314 Reactor Cooling

    [算法]有上下界网络流-无源汇(循环流) [题解]http://www.cnblogs.com/onioncyc/p/6496532.html //未提交 #include<cstdio> ...

  6. hdu 4940 Destroy Transportation system( 无源汇上下界网络流的可行流推断 )

    题意:有n个点和m条有向边构成的网络.每条边有两个花费: d:毁坏这条边的花费 b:重建一条双向边的花费 寻找这样两个点集,使得点集s到点集t满足 毁坏全部S到T的路径的费用和 > 毁坏全部T到 ...

  7. ACM-ICPC 2018 沈阳赛区网络预赛 F Fantastic Graph(贪心或有源汇上下界网络流)

    https://nanti.jisuanke.com/t/31447 题意 一个二分图,左边N个点,右边M个点,中间K条边,问你是否可以删掉边使得所有点的度数在[L,R]之间 分析 最大流不太会.. ...

  8. 算法笔记--最大流和最小割 && 最小费用最大流 && 上下界网络流

    最大流: 给定指定的一个有向图,其中有两个特殊的点源S(Sources)和汇T(Sinks),每条边有指定的容量(Capacity),求满足条件的从S到T的最大流(MaxFlow). 最小割: 割是网 ...

  9. POJ 2396 Budget(有源汇上下界网络流)

    Description We are supposed to make a budget proposal for this multi-site competition. The budget pr ...

随机推荐

  1. Hadoop(4)--Hbase

    Hadoop 其它组成角色介绍--Hbase 在apache的官方网站上,对于Hbase的定义是他是Hadoop的第一个分布式.可扩展的大数据存储的数据库,他的目标是将非常大的表托管到一个集群中进行相 ...

  2. python学习之常用模块

  3. debounce、throttle、requestAnimationFrame

    今天review同事代码,代码实现了返回顶部的功能,用到了lodash库中的throttle,我看着眼生,于是乎去看了下lodash文档,然后牵出了debounce,具体的知识点,这里不再赘述,底部的 ...

  4. HBase 高级架构解析

    整体框架 使用 ZooKeeper 框架协助 RegionServer(类似于HDFS的nodemanager)用户请求从 Client 到 Zookeeper 进行判断数据属于哪一个 Region ...

  5. 通过transpose和flip实现图像旋转90/180/270度

    在fbc_cv库中,提供了对图像进行任意角度旋转的函数rotate,其实内部也是调用了仿射变换函数warpAffine.如果图像仅是进行90度倍数的旋转,是没有必要用warpAffine函数的.这里通 ...

  6. (转载)深入super,看Python如何解决钻石继承难题

    1.   Python的继承以及调用父类成员 python子类调用父类成员有2种方法,分别是普通方法和super方法 假设Base是基类 class Base(object): def __init_ ...

  7. Phoenix映射HBase数据表

    1. 说明 安装好phoenix后对于HBase中已经存在的数据表不会自动进行映射,所以想要再phoenix中操作HBase已有数据表就需要手动进行配置. 2. 创建HBase表 > creat ...

  8. java二分法来求一个数组中一个值的key

    package TestArray; import java.util.Arrays; /** * 二分法查找 */ public class Test { public static void ma ...

  9. 添加用户-查看用户列表-禁止默认root登陆

    程序小屌丝狒狒: (Q971751392) linux添加用户 adduser feifei passwd [用户名] 设置密码 可以查看所有用户的列表 cat /etc/passwd  w 可以查看 ...

  10. Linux下启动Oracle服务和监听程序步骤

    Linux下启动Oracle服务和监听程序启动和关闭步骤整理如下: 1.安装oracle: 2.创建oracle系统用户: 3./home/oracle下面的.bash_profile添加几个环境变量 ...