• SGU 194 Reactor Cooling Dinic求解 无源无汇有上下界的可行流


    题目链接

    题意:有向图中有n(1 <= n <= 200)个点,无自环或者环的节点个数至少为3.给定每条边的最小流量和最大流量,问每条边的可行流量为多少?

    思路:一般求解的网络流并不考虑下界问题,即流量可以为0,在有下界时,我们只需将上界变成r-l,这时还需要满足流量守恒,增加源点s和汇点t,当点u的流入大于流出时,将点u与s连边,容量即为多出的流量。同理当u流出大于流入时,多出来的流出的流量连到汇点t;直接跑最大流;这时得到的只是网络中的可行流;

    为什么处理完下界之后是这样与超级源点和汇点连边的?

    因为我们建的图是建立在每条边已经满足下界的情况下的,但是这时并没有实现流量的平衡。这时就需要显式地对没有流出的流量增加流入边,即上面当输入的流量-流出的流量>0时,与源点连边。因为我们之后跑完Dinic之后,看附加边是否满流,看的就是是否填补了下界没有流出去的流量。从而实现流量平衡;

    ps:对于网络流问题,无论题目的是有向还是无向图,因为是增广搜索,所以一定是建无向图。。只是cap不同

    #include<bits/stdc++.h>
    using namespace std;
    #define rep0(i,l,r) for(int i = (l);i < (r);i++)
    #define rep1(i,l,r) for(int i = (l);i <= (r);i++)
    #define rep_0(i,r,l) for(int i = (r);i > (l);i--)
    #define rep_1(i,r,l) for(int i = (r);i >= (l);i--)
    #define MS0(a) memset(a,0,sizeof(a))
    #define MS1(a) memset(a,-1,sizeof(a))
    #define MSi(a) memset(a,0x3f,sizeof(a))
    #define inf 0x3f3f3f3f
    #define lson l, m, rt << 1
    #define rson m+1, r, rt << 1|1
    #define lowbit(x) (x&(-x))
    typedef pair<int,int> PII;
    #define A first
    #define B second
    #define MK make_pair
    typedef long long ll;
    typedef unsigned int uint;
    int i,j,k,n,m;
    const int M = 40000;
    int head[M],tot;
    struct Edge{
        int from,to,cap,flow,Next,id;
        Edge(){}
        Edge(int f,int to,int cap,int Next,int id):from(f),to(to),cap(cap),Next(Next),id(id),flow(0){}
    }e[M<<1];
    inline void ins(int u,int v,int w,int id)
    {
        e[++tot] = Edge{u,v,w,head[u],id};
        head[u] = tot;
    }
    int s,t,cur[M],d[222];
    int que[222];
    bool BFS()
    {
        rep1(i,s,t) d[i] = -1;
        int l = 1,r = 1;
        que[r++] = s;d[s] = 0;
        while(l < r){ //[l,r)
            int u = que[l++];
            for(int i = head[u];i;i = e[i].Next){
                int v = e[i].to;
                if(d[v] < 0 && e[i].cap > e[i].flow){ // 只考虑残量网络的弧
                    d[v] = d[u] + 1;//扑出路径来;
                    que[r++] = v;
                    if(v == t) return true;
                }
            }
        }
        return false;
    }
    int DFS(int x,int a)// a表示目前为止所有弧的最小残量
    {
        if(x == t || a == 0) return a;
        int& i = cur[x];//回溯时会多次DFS到同一个点
        if(i == 0) i = head[x];
        int flow = 0, f;
        for(;i;i = e[i].Next){// 从上次考虑的弧开始
            int v = e[i].to;
            if(d[v] == d[x]+1 && (f = DFS(v,min(a,e[i].cap - e[i].flow))) > 0){
                e[i].flow += f;
                e[i^1].flow -= f;
                flow += f;
                a -= f;// 残量-流量
                if(a == 0)   break;
            }
        }
        return flow;
    }
    int Dinic()
    {
        int flow = 0;
        while(BFS()){//仍然存在增广路时再DFS
            rep1(i,s,t) cur[i] = 0;//记录当前探索到的点的弧的编号
            flow += DFS(s,inf);
        }
        return flow;
    }
    int l[M],ans[M];
    int main()
    {
        //freopen("data.txt","r",stdin);
        //freopen("out.txt","w",stdout);
        int kase = 0;
        while(scanf("%d%d",&n,&m) == 2){
            if(kase++) puts("");
            MS0(head);tot = 1;MS0(d);
            int u,v,r;
            s = 0,t = n+1;
            rep1(i,1,m){
                scanf("%d%d%d%d",&u,&v,&l[i],&r);
                d[u] -= l[i];
                d[v] += l[i];
                ins(u,v,r-l[i],i);
                ins(v,u,0,0);
            }
            rep1(i,1,n){
                if(d[i] > 0) ins(s,i,d[i],0),ins(i,s,0,0);
                if(d[i] < 0) ins(i,t,-d[i],0),ins(t,i,0,0);
            }
            Dinic();
            bool flag = false;
            for(int d = head[s];d;d = e[d].Next){
                if(e[d].cap - e[d].flow){flag = true;break;}
            }
            if(flag){puts("NO");continue;}
            puts("YES");
            rep1(i,2,tot)if(e[i].id){
                ans[e[i].id] = e[i].flow+l[e[i].id];
            }
            rep1(i,1,m) printf("%d
    ",ans[i]);
        }
        return 0;
    }
  • 相关阅读:
    网上Silverlight项目收集
    在Silverlight页面里显示HTML的免费控件下载(附使用方法代码)
    Silverlight SNS项目
    Visual Studio 2010下的RIA开发,Silverlight 4线下技术交流会期待您的参与!
    Windows7硬件展示与客户端信息收集
    Silverlight版的神奇罗盘,仿Google的Flash神奇罗盘
    (解题思路)Entity Framework 如动态创建表或者列
    (学)这些年来的几宗罪
    (学)在SQL2005中使用分区表技术
    (医)有痔青年的福音
  • 原文地址:https://www.cnblogs.com/hxer/p/5347353.html
Copyright © 2020-2023  润新知