最大流模板(sap+gap+当前弧)
来源:互联网 发布:苹果手机测试软件 编辑:程序博客网 时间:2024/04/29 09:11
手抄了书上的模板,将它封装在一个结构体里,以后用起来更方便,对应POJ 1273 模板测试题
#include <cstdio>#include <cstring>#include <climits>#include <algorithm>const int N = 222;int n, m;struct ISAP{int head[N], cnt, ans;int gap[N], curedge[N], d[N], pre[N];// gap:统计高度数量数组;d:距离标号数组;// curedges:当前弧数组;pre:前驱数组 struct node{int cap, to;int next;}edge[N * 10];void initi(){memset(d, 0, sizeof(d));memset(gap, 0, sizeof(gap));memset(pre, -1, sizeof(pre));memset(head, -1, sizeof(head));ans = 0; //初始化最大流为0 cnt = 0;}void addedge(int a, int b, int c){//有向图加边。 edge[cnt].to = b, edge[cnt].cap = c;edge[cnt].next = head[a], head[a] = cnt++;edge[cnt].to = a, edge[cnt].cap = 0;edge[cnt].next = head[b], head[b] = cnt++;}int max_flow(int start, int end){int i, u, tmp, neck;for(i = 1;i <= n;i++)curedge[i] = head[i];//初始化当前弧为第一条邻接边 gap[0] = n;u = start;while(d[start] < n){//当d[start] >= n,网络中肯定出现了gap if(u == end){//增广成功,寻找瓶颈边 int min_flow = INT_MAX;for(i = start;i != end;i = edge[curedge[i]].to){if(min_flow > edge[curedge[i]].cap){neck = i;min_flow = edge[curedge[i]].cap;}}for(i = start;i != end;i = edge[curedge[i]].to){//更新正反向弧流量 tmp = curedge[i];edge[tmp].cap -= min_flow;edge[tmp ^ 1].cap += min_flow;}ans += min_flow;u = neck;//下次增广从瓶颈边开始 }for(i = curedge[u];i != -1;i = edge[i].next)if(edge[i].cap&&d[u] == d[edge[i].to] + 1)//寻找可行弧 break;if(i != -1){curedge[u] = i;pre[edge[i].to] = u;u = edge[i].to;} else {if(--gap[d[u]] == 0)break;curedge[u] = head[u];for(tmp = n, i = head[u];i != -1;i = edge[i].next)if(edge[i].cap)tmp = std::min(tmp, d[edge[i].to]);d[u] = tmp + 1;++gap[d[u]];if(u != start)u = pre[u];//重标号并且从当前点前驱重新增广 }}return ans;}};int main(){while(~scanf("%d%d", &m, &n)){int i, a, b, c;ISAP g;g.initi();//算法开始前,一定要初始化 for(i = 0;i < m;i++){scanf("%d%d%d", &a, &b, &c);g.addedge(a, b, c);}printf("%d\n", g.max_flow(1, n));}return 0;}
开始时初始标号用一次bfs求出,然后再跑最大流,效果更好。。
#include <cstdio>#include <queue>#include <cstring>#include <climits>#include <iostream>#include <algorithm>using namespace std;const int N = 100010;int n, m;struct Edge{ int cap, to; int next;}edge[N * 4];int head[N], cnt, ans, des, src;int gap[N], curedge[N], d[N], pre[N], que[N];void bfs(){ memset(d, -1, sizeof(d)); memset(gap, 0, sizeof(gap)); gap[0] = 1; int front = 0, rear = 0; d[des] = 0; que[rear++] = des; while(front != rear){ int deq = que[front++]; front = front % N; for (int it = head[deq]; it != -1; it = edge[it].next){ int e = edge[it].to; if (edge[it].cap != 0 || d[e] != -1) continue; que[rear++] = e; rear = rear % N; ++gap[d[e] = d[deq] + 1]; } }}struct ISAP{ // gap:统计高度数量数组;d:距离标号数组; // curedges:当前弧数组;pre:前驱数组 void initi(){ fill(d + 1, d + n + 1, 0); fill(pre + 1, pre + n + 1, -1); fill(head + 1, head + n + 1, -1); ans = 0; //初始化最大流为0 cnt = 0; } void addedge(int a, int b, int c){ //有向图加边。 edge[cnt].to = b, edge[cnt].cap = c; edge[cnt].next = head[a], head[a] = cnt++; edge[cnt].to = a, edge[cnt].cap = 0; edge[cnt].next = head[b], head[b] = cnt++; } int max_flow(int start, int end){ int i, u, tmp, neck; bfs(); for(i = 1;i <= n;i++) curedge[i] = head[i]; //初始化当前弧为第一条邻接边 u = start; while(d[start] < n){ //当d[start] >= n,网络中肯定出现了gap if(u == end){ //增广成功,寻找瓶颈边 int min_flow = INT_MAX; for(i = start;i != end;i = edge[curedge[i]].to){ if(min_flow > edge[curedge[i]].cap){ neck = i; min_flow = edge[curedge[i]].cap; } } for(i = start;i != end;i = edge[curedge[i]].to){//更新正反向弧流量 tmp = curedge[i]; edge[tmp].cap -= min_flow; edge[tmp ^ 1].cap += min_flow; } ans += min_flow; u = neck; //下次增广从瓶颈边开始 } for(i = curedge[u];i != -1;i = edge[i].next) if(edge[i].cap&&d[u] == d[edge[i].to] + 1) //寻找可行弧 break; if(i != -1){ curedge[u] = i; pre[edge[i].to] = u; u = edge[i].to; } else { if(--gap[d[u]] == 0) break; curedge[u] = head[u]; for(tmp = n, i = head[u];i != -1;i = edge[i].next) if(edge[i].cap) tmp = std::min(tmp, d[edge[i].to]); d[u] = tmp + 1; ++gap[d[u]]; if(u != start) u = pre[u]; //重标号并且从当前点前驱重新增广 } } return ans; }}g;int main(){ int T; cin >> T; while(T--){ int i, a, b, c, sd = INT_MAX, dd = INT_MIN, x, y; scanf("%d%d", &n, &m); g.initi(); for(i = 1;i <= n;i++){ scanf("%d%d", &x, &y); if(sd > x){ src = i; sd = x; } if(dd < x){ des = i; dd = x; } } for(i = 0;i < m;i++){ scanf("%d%d%d", &a, &b, &c); g.addedge(a, b, c); g.addedge(b, a, c); } printf("%d\n", g.max_flow(src, des)); } return 0;}
- 最大流模板(sap+gap+当前弧)
- 网络流模板-SAP+当前弧优化+gap优化
- 【网络流】【再次更新模板】SAP多路增广+GAP+当前弧
- 最大流:SAP+GAP模版
- 最大流算法 SAP+GAP
- 网络流SAP+GAP模板
- isap算法模板poj 1273gap+弧优化 最大流
- 最大流 SAP模板
- 最大流Sap模板
- 最大流SAP模板
- SAP最大流模板
- poj 3469 最小割模板sap+gap+弧优化
- 网络流SAP+gap+弧优化算法
- HDU4280(Island Transport )最大流SAP算法+当前弧优化
- 网络流最大流EdmondKarp、SAP【模板】
- 网络流最大流sap算法模板
- 网络最大流(SAP)【模板】
- 【最大流之sap】【HDU1532】模板题
- maven eclipse插件抽风的手工解决
- 技术人有个缺陷就是喜欢转牛角尖
- Github for Windows使用图文教程
- Windows下UltraEdit查看Objective-C代码高亮工具
- shell常用知识
- 最大流模板(sap+gap+当前弧)
- json在java应用
- Android Animation 学习笔记
- 添加删除右键菜单打开MS-DOS的方法和批处理
- hive安装及配置
- hdu1048
- centos 安装 STREAMING h264 视频的流播放 关于如何配置APACHE的STREAMING播放MP4的视频.
- Linux下安装TSM
- 看到的一篇文章 觉得不错 转载....