//题意:给定一个有向网络,每条边均有一个容量。问是否存在一个从点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算法是解决最大网络流问题的一种方法,通过迭代标度和增广路径的过程找到网络的最大流量。在实际应用中,可能需要根据具体问题的规模和特性选择最适合的算法。
这里面的内容是个PPT,介绍的很好,如果你想更加的清楚 最大流的原理,这是个不错的选择
原题为USACO 草地排水 模板,网络流,最大流,ISAP算法 虽然可能写的不怎么好看但是带一些注释,应该可以看懂吧。
在本压缩包文件中,我们将探讨两个关键的算法:SAP(Shortest Augmenting Path)算法和ISAP(Iterative Shortest Augmenting Path)算法,它们都是求解网络最大流问题的有效方法。 最大流问题是寻找网络中从源点到...
Isap算法,全称为Incremental Simplex Algorithm for Perfect Matching,是一种用于解决网络流问题中的最大匹配问题的有效算法,尤其适用于求解完全匹配。 首先,我们需要理解一些基本概念。在有向图G=(V,E)中,...
SyncMOS ISAP Delphi Sample Code 是一组专为Delphi编程环境设计的示例代码,旨在帮助开发者理解和实现SyncMOS ISAP(Integrated System Access Protocol)接口。ISAP是一种通信协议,通常用于嵌入式系统或者设备...
### 同步MOS ISAP 用户手册概览 #### ISAP 简介 ISAP (In System Programming) 是一种在线编程技术,允许用户通过特定的接口(如 UART)对微控制器进行编程,无需将其从电路板上拆卸下来。这种技术大大简化了程序...
用C++实现的3种最大流算法。CS(Capacity-Scaling Algorithm)、SAP(Shortest Augmenting Path Algorithm)、ISAP(Improved Shortest Augmenting Path Algorithm)。
《最大网络流算法详解——基于ISAP的邻接表实现》 在计算机科学领域,网络流问题是一个重要的图论问题,广泛应用于各种实际场景,如运输规划、电路设计、资源分配等。本压缩包文件“wll.rar”提供的是一种解决最大...
《北京恒光综合接入设备iSAP2000升级文件及配置指导书》 本文将详细介绍北京恒光通信技术有限公司的iSAP2000综合接入设备的升级过程和配置方法,以帮助用户更好地理解和操作这一先进的网络设备。 一、iSAP2000简介...
最大流问题的解决方案不仅仅局限于EK和ISAP算法,还有其他如Ford-Fulkerson、 Dinic's算法等。Ford-Fulkerson方法与Edmonds-Karp类似,也是基于增广路径,但它可以采用任何路径查找策略,而不仅仅是最短路径。Dinic'...
iSAP MetaWeb中文文档.rar
- **图论算法**:包括最短路径(如 Dijkstra、SPFA、Astar)、网络流(如 Ford-Fulkerson、ISAP)、图的连通性、欧拉回路、树的重心维护、网络流以及图的匹配等。 - **博弈论**:包括 SG 函数、Nim 游戏、Bash ...
在这个问题中,我们关注的是有向图上的网络流,其中每条边都带有容量限制,表示该边可以传输的最大流量。网络流的基本目标是确定从源点s到汇点t的最大可能流量。 1. **网络流定义**: - 网络是由节点(顶点)和有...
**ISAP算法**是一种改进的Dijkstra算法,适用于处理网络流问题,特别是在处理最大流问题时非常高效。 ##### 4. Primal-Dual (原始对偶) 算法 **Primal-Dual算法**主要用于解决带费用的网络流问题,即除了考虑最大...
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
ISAP算法是对EK算法的一种改进,通过引入距离标记来加速寻找最短增广路径的过程,进一步提高了解决最大流问题的效率。ISAP算法的时间复杂度通常为O(V^2E),但在实践中往往比理论上的复杂度表现得更好。 ### 最小...
ERP系统信息化资料:ISAP专业培训教材ntro to ABAP - Chapter 10.ppt