这道题跟求最大流的时候差不多。

都是先构造可行流,然后判断是否可行,

可行的话,就利用残余流量,构造从汇点t跑到源点s的最大流,

如何求出答案呢。

在第一次求可行流的dinic后,跟求最大流的时候一样,从t到s是可行流的流量;

这个时候t到s的反向边,也就是s到t的流量就是t到s流的量(因为t到s定义权值为inf,要从这条边算出来,得用inf去减到这条边剩下的才是答案,有点麻烦)

所以反向边是个便捷的求法。

所以在第一次dinic之后,t到s的反向便的流量就是可行流的流量;

然后我们再从t到s跑最大流,看最大能跑掉多少,就是最后的答案。 (这里肯定不会影响可行流!,因为已经在第一次dinic的时候保证了可行(即sum==tmpp))

求第二次dinic的时候,要将s跟t之间的边给去掉。

  1. #include<cstdio>
  2. #include<string.h>
  3. #include<algorithm>
  4. #include<math.h>
  5. #include<queue>
  6. using namespace std;
  7. typedef long long ll;
  8. const ll maxn=;
  9. const ll inf=0x3f3f3f3f3f3f3f3f;
  10. ll vis[maxn];
  11. ll head[maxn],level[maxn]; //前者为邻接表必要数据,后者为dinic的层 数据
  12. ll in[maxn]; //一条边的初始流量(最低值 也就是定为下界)
  13. ll limit[maxn]; //limit为该点的流量 小于0的时候是流出多
  14. //ll bh[maxn]; //一条边的反向边的流量(正向边流出了多少,反向边就是多少)
  15. //所以用初始的下界流量+上这个方向边的流量就是最终答案;
  16. //那么为什么不直接正向呢???
  17. //废话 正向求比较麻烦嘛。 原本的值是可以流的量,正向边流出去后
  18. //那么答案就是可以流的量减去剩余的量就是答案;
  19. //所以还不如直接求反向呢
  20. ll num; //邻接表
  21. void init()
  22. {
  23. num=- ;
  24. memset(head,-,sizeof(head));
  25. }
  26. struct node
  27. {
  28. ll v,w,next;
  29. }G[maxn*];
  30. ll bfs(ll s,ll t)
  31. {
  32. queue<ll>q;
  33. q.push(s);
  34. memset(level,-,sizeof(level));
  35. level[s]=;
  36. while(!q.empty()){
  37. ll u=q.front();
  38. q.pop();
  39. for(ll i=head[u];i!=-;i=G[i].next){
  40. ll v=G[i].v;
  41. if(G[i].w>&&level[v]==-){
  42. level[v]=level[u]+;
  43. q.push(v);
  44. }
  45. }
  46. }
  47. return level[t];
  48. }
  49. ll dfs(ll s,ll t,ll f)
  50. {
  51. if(s==t) return f;
  52. ll ans=;
  53. for(ll i=vis[s];i!=-;i=G[i].next){
  54. vis[s]=i; //当前弧优化
  55. ll v=G[i].v;
  56. if(G[i].w>&&level[s]+==level[v]){
  57. ll d=dfs(v,t,min(G[i].w,f-ans));
  58. if(d>){
  59. G[i].w-=d;
  60. G[i^].w+=d;
  61. ans+=d;
  62. if(ans==f) return ans;
  63. }
  64. }
  65. }
  66. // if(ans==0) level[s]=0;
  67. return ans;
  68. }
  69. ll dinic(ll s,ll t)
  70. {
  71. ll ans=;
  72. while(){
  73. ll temp=bfs(s,t);
  74. if(temp==-) break;
  75. memcpy(vis,head,sizeof(head));
  76. ans+=dfs(s,t,inf);
  77. }
  78. return ans;
  79. }
  80. void build(ll u,ll v,ll w)
  81. {
  82. num++;
  83. G[num].v=v;
  84. G[num].w=w;
  85. G[num].next=head[u];
  86. head[u]=num;
  87.  
  88. num++;
  89. G[num].v=u;
  90. G[num].w=;
  91. G[num].next=head[v];
  92. head[v]=num;
  93. }
  94. int main()
  95. {
  96. init();
  97. ll n,m,s,t;
  98. scanf("%lld%lld%lld%lld",&n,&m,&s,&t);
  99. for(ll i=;i<=m;i++){
  100. ll u,v,w1,w2;
  101. scanf("%lld%lld%lld%lld",&u,&v,&w1,&w2);
  102. // in[u]=w1;
  103. limit[u]-=w1;
  104. limit[v]+=w1;
  105. build(u,v,w2-w1);
  106. }
  107. ll S=;ll T=n+;
  108. ll sum=;
  109. for(ll i=;i<=n;i++){
  110. if(limit[i]<) build(i,T,-limit[i]);
  111. if(limit[i]>) build(S,i,limit[i]),sum+=limit[i];
  112. }
  113. build(t,s,inf);
  114. //其实这里应该有上面的limit的变化 只是因为这里的w1为0,所以省略不写。
  115. ll tmpp=dinic(S,T);
  116. if(tmpp!=sum) printf("please go home to sleep\n");
  117. else{
  118. ll tmp1=G[num].w;
  119. G[num].w=G[num-].w=;
  120. ll tmp2=dinic(t,s);
  121. printf("%lld\n",tmp1-tmp2);
  122. }
  123. return ;
  124. }

有源汇有上下界最小流 (ZQU 1592)的更多相关文章

  1. loj #117. 有源汇有上下界最小流

    题目链接 有源汇有上下界最小流,->上下界网络流 注意细节,边数组也要算上后加到SS,TT边. #include<cstdio> #include<algorithm> ...

  2. LOJ.117.[模板]有源汇有上下界最小流(Dinic)

    题目链接 有源汇有上下界最小流 Sol1. 首先和无源汇网络流一样建图,求SS->TT最大流: 然后连边(T->S,[0,INF]),再求一遍SS->TT最大流,答案为新添加边的流量 ...

  3. sgu 176 Flow construction(有源汇的上下界最小流)

    [题目链接] http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=11025 [模型] 有源汇点的上下界最小流.即既满足上下界又满足 ...

  4. Flow construction SGU - 176 有源汇有上下界最小流 二分法和回流法

    /** 题目:Flow construction SGU - 176 链接:https://vjudge.net/problem/SGU-176 题意: 有源汇有上下界的最小流. 给定n个点,m个管道 ...

  5. 【 POJ - 3801】Crazy Circuits(有源汇、上下界最小流)

    Description You’ve just built a circuit board for your new robot, and now you need to power it. Your ...

  6. bzoj 2502 清理雪道(有源汇的上下界最小流)

    [题意] 有一个DAG,要求每条边必须经过一次,求最少经过次数. [思路] 有上下界的最小流.  边的下界为1,上界为无穷.构造可行流模型,先不加ts边跑一遍最大流,然后加上t->s的inf边跑 ...

  7. sgu176 Flow Construction【有源汇有上下界最小流】

    同样是模板题. 首先将有源汇转换为无源汇,假设原来的源汇为st,我们加入的源汇为ST,那么我们应该从t到s连一条流量为+∞的边,使原来的st满足收支平衡,退化为普通节点. 分离必要边和其他边,从S到T ...

  8. Crazy Circuits HDU - 3157(有源汇有上下界最小流)

    给出每条边的下界 求最小流 板题 提供两个板子代码 虽然这个题 第一个比较快 但在loj上https://loj.ac/problem/117 的板题  第一个1700+ms 第二个才600+ms   ...

  9. LOJ117 有源汇有上下界最小流(上下界网络流)

    跑出可行流后从原来的汇点向原来的源点跑最大流,原图最小流=inf-maxflow.显然超源超汇的相关边对其也没有影响.原图最小流=可行流-原图新增流量,因为t向s流量增加相当于s向t流量减少.但为什么 ...

  10. 有源汇有上下界最小流 DInic + 各种优化 模板

    例题:loj117 : https://loj.ac/problem/117 //其实就是判断可行流后倒着求一遍最大流 #include <iostream> #include <c ...

随机推荐

  1. linux 6.9 补丁修补漏洞

    1 先将openssh-8.0p1.tar.gz 上传到 root下的/opt 文件夹下 解压  tar -zxvf openssh-8.0p1.tar.gz  -C /opt 2 启动vncserv ...

  2. linux - python:卸载

    [root@test ~]# rpm -qa|grep python|xargs rpm -ev --allmatches --nodeps ##强制删除已安装程序及其关联[root@test ~]# ...

  3. SDOI2010 粟粟的书架 lg2468(可持久化,前缀和)

    题面见https://www.luogu.org/problemnew/show/P2468 然后这道题属于合二为一题,看一眼数据范围就能发现 首先我们先考虑50分,二维前缀和维护一下(反正我不记得公 ...

  4. ubuntu19.04 redis启动和停止及连接

    1.启动停止 如果以(sudo apt install redis-server)方式安装 启动: sudo srevice redis start 停止:     sudo srevice redi ...

  5. jdk8-》lambda

    lambda表达式 使⽤场景(前提):⼀个接⼝中只包含⼀个⽅法,则可以使⽤Lambda表达式,这样的接⼝称之为“函数接⼝” 语法: (params) -> expression   第⼀部分为括 ...

  6. IIS支持json、geojson文件

    最近在搞asp.net + openlayers. 其中openlayer有个数据源支持 .geojson 数据,但是怎么测试都不能成功.同样的数据拿到php下就能成功显示. 搓. 在网上漫无目的的搜 ...

  7. css和js处理隔行换色的问题

      <html> <head> <meta charset="utf-8"> <meta name="" conten ...

  8. web前端基础-css-尺寸边框

    尺寸和边框: 一.尺寸 行内元素是不能设置宽和高的,其高度是由元素里面的内容的高度撑起来的: 行内块元素可以设置宽和高,当行内块元素没有设置宽高的时候,行内块元素的宽高是其默认的宽高: 块级元素:可以 ...

  9. iterations 快捷键

    原帖:https://blog.csdn.net/Soinice/article/details/83505198 为了防止删除备份的. iterations 快捷键 Live Templates 其 ...

  10. python之路之css拾遗

    做一个鼠标碰到就会自动加边框的效果 下边的代码,主要是使自动加边框的时候,加边框的部分不会跳动 实现一张图片的点击之后出现信息