• ZOJ 2314 Reactor Cooling(无源汇有上下界可行流)


    题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2314

    题目大意:

    给n个点,及m根pipe,每根pipe用来流躺液体的,单向的,每时每刻每根pipe流进来的物质要等于流出去的物质,要使得m条pipe组成一个循环体,里面流躺物质。

    并且满足每根pipe一定的流量限制,范围为[Li,Ri].即要满足每时刻流进来的不能超过Ri(最大流问题),同时最小不能低于Li。

    解题思路:

    转自:https://www.cnblogs.com/WABoss/p/5371871.html

    本质上就是求一个无源汇流量有上下界的容量网络的可行流,因为无源汇的容量网络上各个顶点都满足流量平衡条件,即所有点的∑流入流量=∑流出流量,可以看成里面的流是循环流动的,类似有向图欧拉回路。

    而带上下界的网络可行流的求法,是根据网络流中一个流是可行流的充分必要条件——限制条件和平衡条件,去改造原网络,转化成不带下界的容量网络来求解的。数学模型那些证明之类的不难理解,见论文《一种简易的方法求解流量有上下界的网络中网络流问题》。

    而改造的方式好像有两种挺流行的,我用的做法是:

    • 设d[u]为顶点u出边下界和-入边下界和,新建源点、汇点
    • 原网络的弧<u,v>容量设置成其上界-下界
    • 对于每一个顶点u,如果d[u]<0则源点向其连容量-d[u]的边,否则其向汇点连容量d[u]的边
    • 最后如果和源点相关的弧都满流则存在可行流,而各条边的流量+其在原网络的下界就是一个解

    代码

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<cmath>
      5 #include<algorithm>
      6 #include<queue>
      7 #include<vector>
      8 #define LL long long
      9 #define pii pair<int,int>
     10 #define pll pair<long long,long long>
     11 #define rep(i,a,b) for(int i=a;i<=b;i++)
     12 #define per(i,a,b) for(int i=a;i>=b;i--)
     13 #define FAST_IO ios::sync_with_stdio(false);cin.tie(0);
     14 #define bug cout<<"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"<<endl;
     15 #define bugc(_) cout << (#_) << " = " << (_) << endl;
     16 using namespace std;
     17 const int N=2e2+5;
     18 const int M=4e4+5;
     19 const int INF=0x3f3f3f3f;
     20 
     21 struct node{
     22     int to,next,flow;
     23 }edge[M*2];
     24 
     25 int cnt,st,en;
     26 int head[N],dep[N],d[N],low[M];//d[u]为顶点u出边下界和-入边下界和,low[i]记录第i条边的下界 
     27 
     28 void init(){
     29     cnt=2;
     30     memset(head,0,sizeof(head));
     31     memset(d,0,sizeof(d));
     32 }
     33 
     34 void link(int u,int v,int flow){
     35     edge[cnt]=node{v,head[u],flow};
     36     head[u]=cnt++;
     37     edge[cnt]=node{u,head[v],0};
     38     head[v]=cnt++;
     39 }
     40 
     41 int bfs(){
     42     memset(dep,0,sizeof(dep));
     43     dep[st]=1;
     44     queue<int>q;
     45     q.push(st);
     46     while(!q.empty()){
     47         int u=q.front();
     48         q.pop();
     49         for(int i=head[u];i;i=edge[i].next){
     50             node t=edge[i];
     51             if(t.flow&&!dep[t.to]){
     52                 dep[t.to]=dep[u]+1;
     53                 q.push(t.to);
     54             }
     55         }
     56     }
     57     return dep[en];
     58 }
     59 
     60 int dfs(int u,int fl){
     61     if(en==u) return fl;
     62     int tmp=0;
     63     for(int i=head[u];i&&fl;i=edge[i].next){
     64         node &t=edge[i];
     65         if(t.flow&&dep[t.to]==dep[u]+1){
     66             int x=dfs(t.to,min(t.flow,fl));
     67             if(x>0){
     68                 tmp+=x;
     69                 fl-=x;
     70                 t.flow-=x;
     71                 edge[i^1].flow+=x;
     72             }
     73         }
     74     }
     75     if(!tmp) dep[u]=-2;
     76     return tmp;
     77 }
     78 
     79 int dinic(){
     80     int ans=0;
     81     while(bfs()){
     82         while(int d=dfs(st,INF))
     83             ans+=d;
     84     }
     85     return ans;
     86 }
     87 
     88 int main(){
     89     int T;
     90     scanf("%d",&T);
     91     while(T--){
     92         int n,m;
     93         scanf("%d%d",&n,&m);
     94         init();
     95         st=0,en=n+1;
     96         for(int i=1;i<=m;i++){
     97             int u,v,c;
     98             scanf("%d%d%d%d",&u,&v,&low[i],&c);
     99             link(u,v,c-low[i]);
    100             d[u]+=low[i];
    101             d[v]-=low[i];
    102         }
    103         int sum=0;
    104         for(int i=1;i<=n;i++){
    105             if(d[i]<0) link(st,i,-d[i]);
    106             else{
    107                 sum+=d[i];
    108                 link(i,en,d[i]);
    109             }
    110         }
    111         if(sum!=dinic()) puts("NO");
    112         else{
    113             puts("YES");
    114             for(int i=2;i<=2*m;i+=2){
    115                 printf("%d
    ",edge[i^1].flow+low[i>>1]);
    116             }
    117         }
    118         puts("");
    119     }
    120     return 0;
    121 }
  • 相关阅读:
    解读Android 12首个开发者预览版
    Pod创建私有库
    Flutter常用网站
    Flutter常用快捷键
    多个网络请求-并发执行、顺序执行
    小猫爬山问题---贪心算法失效,深度优先搜索优化
    网络基本概念备忘:MAC地址,端口,HTTP状态码
    常见图片文件格式简析
    pdf2xls
    评分卡模型
  • 原文地址:https://www.cnblogs.com/fu3638/p/9892416.html
Copyright © 2020-2023  润新知