• poj 1459 多源汇网络流 ISAP


    题意:

    给n个点,m条边,有np个源点,nc个汇点,求最大流

    思路:

    超级源点把全部源点连起来。边权是该源点的最大同意值;

    全部汇点和超级汇点连接起来,边权是该汇点的最大同意值。

    跑最大流

    code:

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    #include<string>
    #include<queue>
    #include<map>
    #include<set>
    #include<cmath>
    #include<cstdlib>
    using namespace std;
    
    #define INF 0x3f3f3f3f
    #define PI acos(-1.0)
    #define mem(a, b) memset(a, b, sizeof(a))
    
    typedef pair<int,int> pii;
    typedef long long LL;
    //------------------------------
    const int maxn = 205;
    const int maxm = 205 * 205;
    const int max_nodes = maxn;
    
    struct Edge{
          int from, to;
          int capacity, flow;
          Edge(){}
          Edge(int from_, int to_, int capacity_, int flow_){
                from = from_;
                to = to_;
                capacity = capacity_;
                flow = flow_;
          }
    };
    Edge edges[maxm];
    int cnte;
    vector<int> g[maxn];
    void graph_init(){
          cnte = 0;
          for(int i = 0; i < maxn; i++) g[i].clear();
    }
    
    void add_Edge(int from, int to, int cap){
          edges[cnte].from = from;
          edges[cnte].to = to;
          edges[cnte].capacity = cap;
          edges[cnte].flow = 0;
          g[from].push_back(cnte);
          cnte++;
          edges[cnte].from = to;
          edges[cnte].to = from;
          edges[cnte].capacity = 0;
          edges[cnte].flow = 0;
          g[to].push_back(cnte);
          cnte++;
    }
    
    int source;         // 源点
    int sink;           // 汇点
    int p[maxn];   // 可增广路上的上一条弧的编号
    int num[maxn]; // 和 t 的最短距离等于 i 的节点数量
    int cur[maxn]; // 当前弧下标
    int d[maxn];   // 残量网络中节点 i 到汇点 t 的最短距离
    bool visited[maxn];
    int num_nodes, num_edges;
    
    void bfs(){                   // 预处理, 反向 BFS 构造 d 数组
          memset(visited, 0, sizeof(visited));
          queue<int> q;
          q.push(sink);
          visited[sink] = true;
          d[sink] = 0;
          while(!q.empty()){
                int u = q.front(); q.pop();
                for(int i = 0; i < g[u].size(); i++){
                      Edge& e = edges[g[u][i] ^ 1];
                      int v = e.from;
                      if(!visited[v] && e.capacity > e.flow){
                            visited[v] = true;
                            d[v] = d[u] + 1;
                            q.push(v);
                      }
                }
          }
    }
    int augment(){                                        // 增广
          int u = sink, df = INF;
          // 从汇点到源点通过 p 追踪增广路径, df 为一路上最小的残量
          while(u != source){
                Edge& e = edges[p[u]];
                df = min(df, e.capacity - e.flow);
                u = e.from;
          }
          u = sink;
          // 从汇点到源点更新流量
          while(u != source){
                Edge& e = edges[p[u]];
                e.flow += df;
                edges[p[u]^1].flow -= df;
                u = e.from;
          }
          return df;
    }
    int max_flow(){
          int flow = 0;
          bfs();
          memset(num, 0, sizeof(num));
          for(int i = 0; i < num_nodes; i++) num[d[i]] ++; // 这个地方,针对的是点从0開始编号的情况
          int u = source;
          memset(cur, 0, sizeof(cur));
          while(d[source] < num_nodes){
                if(u == sink){
                      flow += augment();
                      u = source;
                }
                bool advanced = false;
                for(int i = cur[u]; i < g[u].size(); i++){
                      Edge& e = edges[g[u][i]];
                      if(e.capacity > e.flow && d[u] == d[e.to] + 1){
                            advanced = true;
                            p[e.to] = g[u][i];
                            cur[u] = i;
                            u = e.to;
                            break;
                      }
                }
                if(!advanced){    //retreat
                      int m = num_nodes - 1;
                      for(int i = 0; i < g[u].size(); i++){
                            Edge& e = edges[g[u][i]];
                            if(e.capacity > e.flow) m = min(m, d[e.to]);
                      }
                      if(--num[d[u]] == 0) break;                    // gap 优化
                      num[d[u] = m+1] ++;
                      cur[u] = 0;
                      if(u != source){
                            u = edges[p[u]].from;
                      }
                }
          }
          return flow;
    }
    //------------------------我是分界线,上面是模板--------------------------
    int np, nc, n, m;
    
    void solve(){
          graph_init();
          int u, v, w;
          char ch;
          for(int i = 1; i <= m; i++){
                while(scanf("%c", &ch)){
                      if(ch == '(') break;
                }
                scanf("%d,%d%c%d",&u,&v,&ch,&w);
                add_Edge(u, v, w);
          }
          for(int i = 1; i <= np; i++){
                while(scanf("%c", &ch)){
                      if(ch == '(') break;
                }
                scanf("%d%c%d",&u, &ch, &w);
                add_Edge(n, u, w);
          }
          for(int i = 1; i <= nc; i++){
                while(scanf("%c", &ch)){
                      if(ch == '(') break;
                }
                scanf("%d%c%d",&v, &ch, &w);
                add_Edge(v, n+1, w);
          }
    
          num_nodes = n+2;
          source = n; sink = n+1;
    
          int ans = max_flow();
          printf("%d
    ",ans);
    }
    int main(){
          while(scanf("%d%d%d%d",&n,&np, &nc, &m) != EOF){
                solve();
          }
          return 0;
    }
    


    最终自己写了一个还不错的最大流啦....窝原来用的那个模板我囧的非常好了啊!

    可是我干囧大家好像都再说Dinic是好。又有人在说ISAP好像更棒啊!

    最终我如今两个都敲一下就好啦~~

    ISAP跟DINIC还是有非常多相似的。


  • 相关阅读:
    JQuery:JQuery语法、选择器、事件处理
    循序渐进DB2(第2版)——DBA系统管理、运维与应用案例
    高级进阶DB2(第2版)——内部结构、高级管理与问题诊断
    DB2数据库性能调整和优化(第2版)
    金融工程中的蒙特卡罗方法
    代数学教程
    拓扑线性空间与算子谱理论
    李代数(第2版)
    编程的修炼(中英双语)
    iOS应用开发详解
  • 原文地址:https://www.cnblogs.com/jzssuanfa/p/7214224.html
Copyright © 2020-2023  润新知