`

UVA11248 最大流ISAP模板

 
阅读更多

 

//题意:给定一个有向网络,每条边均有一个容量。问是否存在一个从点1到点N,流量为C的流。
//如果不存在,是否可以恰好修改一条弧的容量,使得存在这样的流?
//
//分析:先求一次最大流,如果流量至少为C,则直接输出possible,否则需要修改的弧一定是最小割里的弧。
//依次把这些弧的容量增加到C,然后再求最大流,看最大流量是否至少为C即可。
//很可惜,这样写出来的程序会超时,还需要加两个重要的优化。第一个优化是求完最大流后把流量留着,以
//后每次在它的基础上增广,第二个优化是每次没必要求出最大流,增广到流量至少为C时就停下来
#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
#include<algorithm>
using namespace std;

const int maxn = 100 + 10;
const int INF = 1000000000;

struct Edge {
  int from, to, cap, flow;
};

bool operator < (const Edge& a, const Edge& b) {
  return a.from < b.from || (a.from == b.from && a.to < b.to);
}

struct ISAP {
  int n, m, s, t;
  vector<Edge> edges;
  vector<int> G[maxn];   // 邻接表,G[i][j]表示结点i的第j条边在e数组中的序号
  bool vis[maxn];        // BFS使用
  int d[maxn];           // 从起点到i的距离
  int cur[maxn];        // 当前弧指针
  int p[maxn];          // 可增广路上的上一条弧
  int num[maxn];        // 距离标号计数

  void AddEdge(int from, int to, int cap) {//添加边
    edges.push_back((Edge){from, to, cap, 0});//注意:有的编译器不支持这里
    edges.push_back((Edge){to, from, 0, 0});
    m = edges.size();
    G[from].push_back(m-2);
    G[to].push_back(m-1);
  }

  bool BFS() {
    memset(vis, 0, sizeof(vis));
    queue<int> Q;
    Q.push(t);
    vis[t] = 1;
    d[t] = 0;
    while(!Q.empty()) {
      int x = Q.front(); Q.pop();
      for(int i = 0; i < G[x].size(); i++) {
        Edge& e = edges[G[x][i]^1];
        if(!vis[e.from] && e.cap > e.flow) {
          vis[e.from] = 1;
          d[e.from] = d[x] + 1;
          Q.push(e.from);
        }
      }
    }
    return vis[s];
  }

  void ClearAll(int n) {//初始化
    this->n = n;
    for(int i = 0; i < n; i++) G[i].clear();
    edges.clear();
  }

  void ClearFlow() {//清空流量
    for(int i = 0; i < edges.size(); i++) edges[i].flow = 0;
  }

  int Augment() {
    int x = t, a = INF;
    while(x != s) {
      Edge& e = edges[p[x]];
      a = min(a, e.cap-e.flow);
      x = edges[p[x]].from;
    }
    x = t;
    while(x != s) {
      edges[p[x]].flow += a;
      edges[p[x]^1].flow -= a;
      x = edges[p[x]].from;
    }
    return a;
  }

  int Maxflow(int s, int t, int need) {//如果达到need,就结束,达不到,就返回最大
    this->s = s; this->t = t;
    int flow = 0;
    BFS();
    memset(num, 0, sizeof(num));
    for(int i = 0; i < n; i++) num[d[i]]++;
    int x = s;
    memset(cur, 0, sizeof(cur));
    while(d[s] < n) {
      if(x == t) {
        flow += Augment();
        if(flow >= need) return flow;
        x = s;
      }
      int ok = 0;
      for(int i = cur[x]; i < G[x].size(); i++) {
        Edge& e = edges[G[x][i]];
        if(e.cap > e.flow && d[x] == d[e.to] + 1) { // Advance
          ok = 1;
          p[e.to] = G[x][i];
          cur[x] = i; // 注意
          x = e.to;
          break;
        }
      }
      if(!ok) { // Retreat
        int m = n-1; // 初值注意
        for(int i = 0; i < G[x].size(); i++) {
          Edge& e = edges[G[x][i]];
          if(e.cap > e.flow) m = min(m, d[e.to]);
        }
        if(--num[d[x]] == 0) break;
        num[d[x] = m+1]++;
        cur[x] = 0; // 注意
        if(x != s) x = edges[p[x]].from;
      }
    }
    return flow;
  }

  vector<int> Mincut() { //可以找出瓶颈路,需要先调用Maxflow
    BFS();
    vector<int> ans;
    for(int i = 0; i < edges.size(); i++) {
      Edge& e = edges[i];
      if(!vis[e.from] && vis[e.to] && e.cap > 0) ans.push_back(i);
    }
    return ans;
  }

  void Reduce() {//优化部分,把已经用的流量删除掉,再算需要增加哪条路的流量
    for(int i = 0; i < edges.size(); i++) edges[i].cap -= edges[i].flow;
  }

  void print() {//测试用
    printf("Graph:\n");
    for(int i = 0; i < edges.size(); i++)
      printf("%d->%d, %d, %d\n", edges[i].from, edges[i].to , edges[i].cap, edges[i].flow);
  }
};

ISAP g;

int main() {
  int n, e, c, kase = 0;
  while(scanf("%d%d%d", &n, &e, &c) == 3 && n) {
    g.ClearAll(n);
    while(e--) {
      int b1, b2, fp;
      scanf("%d%d%d", &b1, &b2, &fp);
      g.AddEdge(b1-1, b2-1, fp);//算法从0开始,如果是双向的,要看做两个单向的
    }
    int flow = g.Maxflow(0, n-1, INF);//计算从0到n-1的最大流
    printf("Case %d: ", ++kase);
    if(flow >= c) printf("possible\n");
    else {
      vector<int> cut = g.Mincut();
      g.Reduce();
      vector<Edge> ans;
      for(int i = 0; i < cut.size(); i++) {
        Edge& e = g.edges[cut[i]];
        e.cap = c;
        g.ClearFlow();
        if(flow + g.Maxflow(0, n-1, c-flow) >= c) ans.push_back(e);
        e.cap = 0;//把修改后能达到c的路都保存起来
      }
      if(ans.empty()) printf("not possible\n");
      else {
        sort(ans.begin(), ans.end());
        printf("possible option:(%d,%d)", ans[0].from+1, ans[0].to+1);
        for(int i = 1; i < ans.size(); i++)
          printf(",(%d,%d)", ans[i].from+1, ans[i].to+1);
        printf("\n");
      }
    }
  }
  return 0;
}

 

 

 

 

分享到:
评论

相关推荐

    isap最大流模板

    最大流问题旨在寻找网络中从源节点到汇点的最大流量,而ISAP模板则是一种求解这一问题的有效方法。 在图论中,网络流模型由一个带权有向图表示,其中每条边代表可以传输流量的连接,并且每条边都有一个容量限制。源...

    最大网络流ISAP算法

    最大网络流问题是一个在图论和运筹学中...总的来说,ISAP算法是解决最大网络流问题的一种方法,通过迭代标度和增广路径的过程找到网络的最大流量。在实际应用中,可能需要根据具体问题的规模和特性选择最适合的算法。

    最大流算法 isap和ek

    这里面的内容是个PPT,介绍的很好,如果你想更加的清楚 最大流的原理,这是个不错的选择

    ISAP算法模板

    原题为USACO 草地排水 模板,网络流,最大流,ISAP算法 虽然可能写的不怎么好看但是带一些注释,应该可以看懂吧。

    图论- 网络流- 最大流- SAP 算法与 ISAP 算法.rar

    在本压缩包文件中,我们将探讨两个关键的算法:SAP(Shortest Augmenting Path)算法和ISAP(Iterative Shortest Augmenting Path)算法,它们都是求解网络最大流问题的有效方法。 最大流问题是寻找网络中从源点到...

    网络流之Isap算法(PPT)

    Isap算法,全称为Incremental Simplex Algorithm for Perfect Matching,是一种用于解决网络流问题中的最大匹配问题的有效算法,尤其适用于求解完全匹配。 首先,我们需要理解一些基本概念。在有向图G=(V,E)中,...

    SyncMOS ISAP Delphi Sample Code

    SyncMOS ISAP Delphi Sample Code 是一组专为Delphi编程环境设计的示例代码,旨在帮助开发者理解和实现SyncMOS ISAP(Integrated System Access Protocol)接口。ISAP是一种通信协议,通常用于嵌入式系统或者设备...

    ISAP_UserManual_TC

    ### 同步MOS ISAP 用户手册概览 #### ISAP 简介 ISAP (In System Programming) 是一种在线编程技术,允许用户通过特定的接口(如 UART)对微控制器进行编程,无需将其从电路板上拆卸下来。这种技术大大简化了程序...

    Maximum_flow.rar_ISAP algorithm_SAP_capacity_capacity scaling_最大

    用C++实现的3种最大流算法。CS(Capacity-Scaling Algorithm)、SAP(Shortest Augmenting Path Algorithm)、ISAP(Improved Shortest Augmenting Path Algorithm)。

    wll.rar_最大网络流

    《最大网络流算法详解——基于ISAP的邻接表实现》 在计算机科学领域,网络流问题是一个重要的图论问题,广泛应用于各种实际场景,如运输规划、电路设计、资源分配等。本压缩包文件“wll.rar”提供的是一种解决最大...

    北京恒光综合接入设备iSAP2000升级文件及配置指导书

    《北京恒光综合接入设备iSAP2000升级文件及配置指导书》 本文将详细介绍北京恒光通信技术有限公司的iSAP2000综合接入设备的升级过程和配置方法,以帮助用户更好地理解和操作这一先进的网络设备。 一、iSAP2000简介...

    最大流入门资料(包含2个清晰的PDF)

    最大流问题的解决方案不仅仅局限于EK和ISAP算法,还有其他如Ford-Fulkerson、 Dinic's算法等。Ford-Fulkerson方法与Edmonds-Karp类似,也是基于增广路径,但它可以采用任何路径查找策略,而不仅仅是最短路径。Dinic'...

    iSAP MetaWeb中文文档.rar

    iSAP MetaWeb中文文档.rar

    ACM程序设计竞赛模板完全版

    - **图论算法**:包括最短路径(如 Dijkstra、SPFA、Astar)、网络流(如 Ford-Fulkerson、ISAP)、图的连通性、欧拉回路、树的重心维护、网络流以及图的匹配等。 - **博弈论**:包括 SG 函数、Nim 游戏、Bash ...

    網絡流c++版.pptx

    在这个问题中,我们关注的是有向图上的网络流,其中每条边都带有容量限制,表示该边可以传输的最大流量。网络流的基本目标是确定从源点s到汇点t的最大可能流量。 1. **网络流定义**: - 网络是由节点(顶点)和有...

    网络流基础

    **ISAP算法**是一种改进的Dijkstra算法,适用于处理网络流问题,特别是在处理最大流问题时非常高效。 ##### 4. Primal-Dual (原始对偶) 算法 **Primal-Dual算法**主要用于解决带费用的网络流问题,即除了考虑最大...

    kuangbin acm模板超级好用

    1 字符串处理 5 1.1 KMP . . . . . . . . ....1.2 e-KMP ....1.3 Manacher ....1.4 AC 自动机 ....1.5 后缀数组 ....1.5.1 DA ....1.5.2 DC3 ....1.6 后缀自动机 ....1.6.1 基本函数 ....1.6.2 例题 ....1.7 字符串 hash ....2.1 素数 ....

    ERP系统信息化资料:ISAP专业培训教材T战略2.ppt

    ERP系统信息化资料:ISAP专业培训教材T战略2.ppt

    ACM模板总结

    ISAP算法是对EK算法的一种改进,通过引入距离标记来加速寻找最短增广路径的过程,进一步提高了解决最大流问题的效率。ISAP算法的时间复杂度通常为O(V^2E),但在实践中往往比理论上的复杂度表现得更好。 ### 最小...

    ERP系统信息化资料:ISAP专业培训教材ntro to ABAP - Chapter 10.ppt

    ERP系统信息化资料:ISAP专业培训教材ntro to ABAP - Chapter 10.ppt

Global site tag (gtag.js) - Google Analytics