zoukankan      html  css  js  c++  java
  • SGU 176 Flow construction (有源有汇有上下界最小流)

    题意:给定 n 个点,m 条有向边,如果有向边的标号是1的话,就表示该边的上界下界都为容量 ,如果有向边的标号为0的哈,表示该边的下界为0,上界为容量 ,
    现在问,从 1 到 n 的最小流是多少,并输出每条边的流量。

    析:首先吐槽一下这个题,我数组开小了,还有网络流写错一个符号,为什么都是PE,而不是 WA 或者是RE,很不能理解。

    这个题目是一个有源有汇有上下界最小流,首先处理所有输入的边,记录每个点的下界流入的流量与流出流量的差,如果这个差大于 0,那么就从超级源点 s连一条 i 的边,容量就是差值,如果是这个值小于 0,那么从 i 到超级汇点 t 连一条边,容量为这个值的相反数,然后对于原先的边,连接的都是上界减下界的容量。

    然后从跑一次 s -> t 最大流,然后再连一条边 n -> 1 容量为无穷大,然后再跑一次 s -> t 最大流,如果这次的和等于原来每个点的下界流入的流量与流出流量的差大于0 的和,那么就是有解,否则就是无解,如果有解,只要按顺序输出每条边的流量加上下界就好了。

    代码如下:

    #pragma comment(linker, "/STACK:1024000000,1024000000")
    #include <cstdio>
    #include <string>
    #include <cstdlib>
    #include <cmath>
    #include <iostream>
    #include <cstring>
    #include <set>
    #include <queue>
    #include <algorithm>
    #include <vector>
    #include <map>
    #include <cctype>
    #include <cmath>
    #include <stack>
    #include <sstream>
    #include <list>
    #include <assert.h>
    #include <bitset>
    #include <numeric>
    #define debug() puts("++++")
    #define gcd(a, b) __gcd(a, b)
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define fi first
    #define se second
    #define pb push_back
    #define sqr(x) ((x)*(x))
    #define ms(a,b) memset(a, b, sizeof a)
    #define sz size()
    #define be begin()
    #define ed end()
    #define pu push_up
    #define pd push_down
    #define cl clear()
    #define lowbit(x) -x&x
    //#define all 1,n,1
    #define FOR(i,n,x)  for(int i = (x); i < (n); ++i)
    #define freopenr freopen("in.in", "r", stdin)
    #define freopenw freopen("out.out", "w", stdout)
    using namespace std;
    
    typedef long long LL;
    typedef unsigned long long ULL;
    typedef pair<int, int> P;
    const int INF = 0x3f3f3f3f;
    const LL LNF = 1e17;
    const double inf = 1e20;
    const double PI = acos(-1.0);
    const double eps = 1e-8;
    const int maxn = 100 + 50;
    const int maxm = 1e6 + 10;
    const LL mod = 1000000007;
    const int dr[] = {-1, 1, 0, 0, 1, 1, -1, -1};
    const int dc[] = {0, 0, 1, -1, 1, -1, 1, -1};
    const char *de[] = {"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"};
    int n, m;
    const int mon[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    const int monn[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    inline bool is_in(int r, int c) {
      return r >= 0 && r < n && c >= 0 && c < m;
    }
    inline int readInt(){ int x;  scanf("%d", &x);  return x; }
    
    struct Edge{
      int from, to, cap, flow;
    };
    
    struct Dinic{
      int n, m, s, t;
      vector<Edge> edges;
      vector<int> G[maxn];
      bool vis[maxn];
      int d[maxn];
      int cur[maxn];
      
      void init(int n){  
        FOR(i, n, 0)  G[i].cl;
        edges.cl;
      }
      
      void addEdge(int from, int to, int cap){
        edges.pb((Edge){from, to, cap, 0});
        edges.pb((Edge){to, from, 0, 0});
        m = edges.sz;
        G[from].pb(m - 2);
        G[to].pb(m - 1); 
      }
      
      bool bfs(){
        ms(vis, 0);  d[s] = 0;  vis[s] = 1;
        queue<int> q;  q.push(s);
        
        while(!q.empty()){
          int u = q.front();  q.pop();
          for(int i = 0; i < G[u].sz; ++i){
            Edge &e = edges[G[u][i]];
            if(!vis[e.to] && e.cap > e.flow){
              vis[e.to] = 1;
              d[e.to] = d[u] + 1;
              q.push(e.to);
            }
          }
        }
        return vis[t];
      }
      
      int dfs(int u, int a){
        if(u == t || a == 0)  return a;
        int flow = 0, f;
        for(int &i = cur[u]; i < G[u].sz; ++i){
          Edge &e = edges[G[u][i]];
          if(d[e.to] == d[u] + 1 && (f = dfs(e.to, min(a, e.cap-e.flow))) > 0){
            e.flow += f;
            edges[G[u][i]^1].flow -= f;
            flow += f;
            a -= f;
            if(a == 0)  break;
          }
        }
        return flow;
      }
      
      int maxFlow(int s, int t){
        this->s = s; this->t = t;
        int flow = 0;
        while(bfs()){ ms(cur, 0);  flow += dfs(s, INF); }
        return flow;
      }
    };
    
    Dinic dinic;
    int down[maxn*maxn];
    int in[maxn];
    
    int main(){
      while(scanf("%d %d", &n, &m) == 2){
        assert(m);
        assert(n);
        int s = 0, t = n + 1;
        int ans = 0;
        dinic.init(t + 5);  ms(in, 0);
        for(int i = 0; i < m; ++i){
          int a, b, c, d;
          scanf("%d %d %d %d", &a, &b, &c, &d);
          int w = 0;
          if(d){
            w = c;
            dinic.addEdge(a, b, 0);
          }
          else  dinic.addEdge(a, b, c);
          down[i] = w;
          in[b] += w;
          in[a] -= w;
        }
        for(int i = 1; i <= n; ++i){
          if(in[i] > 0)  dinic.addEdge(s, i, in[i]), ans += in[i];
          else if(in[i] < 0)  dinic.addEdge(i, t, -in[i]);
        }
        int flow = dinic.maxFlow(s, t);
        dinic.addEdge(n, 1, INF);
        flow += dinic.maxFlow(s, t);
        if(flow != ans){ puts("Impossible");  continue; }
        printf("%d
    ", dinic.edges[(int)dinic.edges.sz-2].flow);
        for(int i = 0; i < m; ++i)
          printf("%d%c", dinic.edges[i<<1].flow + down[i], " 
    "[i+1==m]);
      }
      return 0;
    }
    

      

  • 相关阅读:
    HDOJ1269 迷宫城堡
    最长公共子序列 nyoj36
    HDU1081 To The Max 求子矩阵最大和
    nyoj20 吝啬的国度
    景观分析工具:arcgis中patch analysis模块
    景观格局动态变化分析方法(基于ArcGIS、Fragstats、ENVI、ERDAS、Patch Analysis for ArcGIS) (20110315 08:07:03)
    从C#到Python —— 谈谈我学习Python一周来的体会
    如何判定多边形是顺时针还是逆时针
    超新星与暗能量的发现--今年诺贝尔物理奖工作的介绍(转)
    怎样把扫描好的身份证打印出实际大小
  • 原文地址:https://www.cnblogs.com/dwtfukgv/p/8969559.html
Copyright © 2011-2022 走看看