zoukankan      html  css  js  c++  java
  • sgu Flow construction

                              Flow construction

     

    题目:

      给出N个节点M条水管,要求在满足上下界的情况下。满足起点最小的流量。

     

    算法:

       这是最小流????不知道。仅仅知道用求解上下界最大流的方法就过了。

       做这题收获了非常多东西。

    知道了同一点的flow是真实的流量值,尽管曾经在书上或论文中看到过,只是印象不深,可是经过这题深刻的懂了。就是这题输出的时候有点麻烦。

    。。要记录每次的路径。然后用我刚才说的那个。同一个点的flow是真实的流量值!!!!

     

    #include <iostream>
    #include <algorithm>
    #include <vector>
    #include <queue>
    #include <cstdio>
    #include <cstring>
    using namespace std;
    
    const int INF = 1 << 28;
    const int MAXN = 200 + 10;
    ///////////////////////////////////////
    
    //上下界最小流
    
    struct Edge{
        int from,to,cap,flow,cost;
        Edge(){};
        Edge(int _from,int _to,int _cap,int _flow)
            :from(_from),to(_to),cap(_cap),flow(_flow){};
    };
    vector<Edge> edges;
    vector<int> G[MAXN];
    int cur[MAXN],d[MAXN];
    bool vst[MAXN];
    int N,M,src,sink;
    
    
    ////////////////////////////////
    
    //上下界网络流
    int sum;
    int in[MAXN],id[MAXN*MAXN],low[MAXN*MAXN];
    
    
    void init(){
        src = N + 2; sink = src + 1;
        for(int i = 0;i <= sink;++i)
            G[i].clear();
        edges.clear();
    }
    
    void addEdge(int from,int to,int cap){
        edges.push_back(Edge(from,to,cap,0));
        edges.push_back(Edge(to,from,0,0));
        int sz = edges.size();
        G[from].push_back(sz - 2);
        G[to].push_back(sz - 1);
    }
    
    bool BFS(){
        memset(vst,0,sizeof(vst));
        queue<int> Q;
        vst[src] = 1;
        d[src] = 0;
        Q.push(src);
    
        while(!Q.empty()){
            int x = Q.front(); Q.pop();
            for(int i = 0;i < (int)G[x].size();++i){
                Edge& e = edges[G[x][i]];
                if(!vst[e.to] && e.cap > e.flow){
                    vst[e.to] = 1;
                    d[e.to] = d[x] + 1;
                    Q.push(e.to);
                }
            }
        }
    
        return vst[sink];
    }
    
    int DFS(int x,int a){
        if(x == sink||a == 0)
            return a;
    
        int flow = 0,f;
        for(int& i = cur[x];i < (int)G[x].size();++i){
            Edge& e = edges[G[x][i]];
            if(d[e.to] == d[x] + 1&&(f = DFS(e.to,min(a,e.cap - e.flow))) > 0){
                e.flow += f;
                edges[G[x][i]^1].flow -= f;
                flow += f;
                a -= f;
                if(a == 0) break;
            }
        }
        return flow;
    }
    
    int maxFlow(){
       int flow = 0;
       while(BFS()){
           memset(cur,0,sizeof(cur));
           flow += DFS(src,INF);
       }
       return flow;
    }
    
    void solve(){
       for(int i = 1;i <= N;++i){
           if(in[i] > 0){
              sum += in[i];
              addEdge(src,i,in[i]);
           } else {
              addEdge(i,sink,-in[i]);
           }
       }
    
       sum -= maxFlow();
       addEdge(N,1,INF);   //是图变成无源无汇
       int flow = maxFlow();
    
       if(flow != sum){
           puts("Impossible");
           return;
       }
    
       int sz = edges.size();    //N --> 1 的容量
       printf("%d
    ",edges[sz - 2].flow);  //反向弧的流量。即为正向真实流的流量!!!
       for(int i = 0;i < M;++i){
          if(low[i] > 0)
             printf("%d%c",low[i],i == M - 1 ? '
    ':' ');
          else
             printf("%d%c",edges[id[i]].flow,i == M - 1 ? '
    ':' ');
       }
    
    
    }
    
    int main()
    {
        while(scanf("%d%d",&N,&M) == 2){
            init();
            int x,y,c,d;
            sum = 0;
            memset(in,0,sizeof(in));
    
            for(int i = 0; i < M;++i){
                scanf("%d%d%d%d",&x,&y,&c,&d);
                if(d == 0){              //流量没限制
                   id[i] = edges.size();
                   addEdge(x,y,c);
    
                } else {
                   //sum += c;
                   in[x] -= c;
                   in[y] += c;
                   low[i] = c;
                  // addEdge(src,y,c);        
                   //id[i] = edges.size();   //反向弧的流量,即为正向真实流的流量!!!
                   //addEdge(x,sink,c);
                }
            }
    
            solve();
        }
        return 0;
    }
    
    
    


     

    版权声明:本文博主原创文章,博客,未经同意不得转载。

  • 相关阅读:
    15.手写数字识别-小数据集(load_digits)
    14.深度学习-卷积
    13-垃圾邮件分类2
    12.朴素贝叶斯-垃圾邮件分类
    11.分类与监督学习,朴素贝叶斯分类算法
    9.主成分分析
    关于core_UI的安装和使用
    2020系统综合实践 期末大作业 15组
    2020系统综合实践 第7次实践作业 26组
    第6次实践作业
  • 原文地址:https://www.cnblogs.com/hrhguanli/p/4869983.html
Copyright © 2011-2022 走看看