P3376 【模板】网络最大流( Edmonds-krap、Dinic、ISAP 算法)

题目描述 如题,给出一个网络图,以及其源点和汇点,求出其网络最大流。

输入格式 第一行包含四个正整数N、M、S、T,分别表示点的个数、有向边的个数、源点序号、汇点序号。

接下来M行每行包含三个正整数ui、vi、wi,表示第i条有向边从ui出发,到达vi,边权为wi(即该边最大流量为wi)

输出格式 一行,包含一个正整数,即为该网络的最大流。

输入输出样例

输入 #1 复制
4 5 4 3
4 2 30
4 3 20
2 3 20
2 1 30
1 3 40
输出 #1 复制
50

说明/提示
时空限制:1000ms,128M

数据规模:

对于30%的数据:N<=10,M<=25

对于70%的数据:N<=200,M<=1000

对于100%的数据:N<=10000,M<=100000

样例说明:

题目中存在3条路径:

4–>2–>3,该路线可通过20的流量

4–>3,可通过20的流量

4–>2–>1–>3,可通过10的流量(边4–>2之前已经耗费了20的流量)

故流量总计20+20+10=50。输出50。

思路

最大流板子。。。。
大佬博客传送门1
传送门2
传送门3
传说门4

题解一(Edmonds-krap)

#include<iostream>
#include<cstring>
#include<queue>
using namespace std;#define INF 0x3f3f3f3f
const int maxn = 10005;
const int maxm = 300005;
int n,m,s,e;struct Edge
{int u,v,next;int cap,flow;
} edge[2*maxm];
int head[2*maxm];int k = -1;
void Add(int u, int v, int w)
{edge[++ k] = (Edge){ u, v, head[u], w, 0};head[u] = k;edge[++ k] = (Edge){ v, u, head[v], 0, 0};head[v] = k;
}
int flag = 0;  //flag == 0 表示还能找到增广路int bfs(int s, int e)
{int min_flow[maxn];     //min_flow[i] 表示到达第 i 号节点时,之前所有的路径中 最小的 边的流量cap - 已经流过的流量flowint pre[maxm];          //记录增光路时,当前节点是由那个那条边找到的,这样在找到增光路之后,我们可以根据 pre[] 数组回推其他 组成该增光路的边memset(min_flow, 0, sizeof(min_flow));       //min_flow[i] == 0 表示之前没有走过 i 节点min_flow[s] = INF;pre[s] = -1;queue<int> q;q.push(s);int u,v,flow;while(! q.empty()){u = q.front(); q.pop();for(int i = head[u]; i != -1; i = edge[i].next){v = edge[i].v;flow = edge[i].cap - edge[i].flow;if(flow > 0 && ! min_flow[v])   //所走的这条边还有 剩余的空间cap,并且该节点还没有被走过。。{pre[v] = i;min_flow[v] = min(min_flow[u], flow);q.push(v);}}if(min_flow[e])break;}if(! min_flow[e])       //一只到更新结束,终点到最小增加值还是等于0,那么说从起点到终点已经没有增广路了flag = 1;//这一点千万不要忘,,,,把用过的水流在这条增光路上都减去。。。。for(int j = e; pre[j] != -1;  j = edge[pre[j]].u){edge[pre[j]].flow += min_flow[e];edge[pre[e]^1].flow -= min_flow[e];}return min_flow[e];     //返回最小增加值到 答案中
}int max_flow()
{int mx_flw = 0;while(1){mx_flw += bfs(s, e);if(flag)break;}return mx_flw;
}void init()
{memset(head, -1, sizeof(head));k = -1;
}int main()
{ios::sync_with_stdio(false); cin.tie(nullptr);//freopen("T.txt","r",stdin);cin >> n >> m >> s >> e;init();int u,v,w;for(int i = 1; i <= m; i ++){cin >> u >> v >> w;Add(u, v, w);}cout << max_flow() << endl;return 0;
}

题解二(Dinic)

#include<iostream>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;#define INF 1e9
#define ll long long
const int maxn = 100005;
const int maxm = 150000;
int n,m;struct Edge
{int v;ll w;int next;
} edge[maxm];
int head[maxn], cur[maxn];
int deep[maxn];int k;
void Add(int u, int v, ll w)
{edge[++ k] = (Edge){ v, w, head[u]};head[u] = k;edge[++ k] = (Edge){ u, 0, head[v]};head[v] = k;
}
//bfs 为图分层bool bfs(int s, int e)
{memset(deep, 0x7f, sizeof(deep));for(int i = 1; i <= n; i ++) cur[i] = head[i];deep[s] = 0;queue<int> q;q.push(s);int u,v;ll w;while(! q.empty()){u = q.front(); q.pop();for(int i = head[u]; i != -1; i = edge[i].next){v = edge[i].v;w = edge[i].w;if(w && deep[v] > INF){deep[v] = deep[u] + 1;q.push(v);}}}if(deep[e] >= INF)return false;return true;
}//dfs 一次找多条增光路(相当于找了一个增广网。。)
ll dfs(int now, int e, ll limit)
{if(! limit || now == e) return limit;ll flow = 0, f;for(int i = cur[now]; i != -1; i = edge[i].next){cur[now] = i;   //千万注意这一步的意思啊。。这一步是因为 dfs的特性是每次增广一定是增广,那么下一次就不必再检查它了,而直接看第一个未被检查的边if(deep[edge[i].v] == deep[now] + 1 && (f = dfs(edge[i].v, e, min(limit, edge[i].w)))){flow += f;limit -= f;edge[i].w -= f;edge[i^1].w += f;if(! limit)break;}}return flow;
}ll Dinic(int s, int e)
{ll mx_flw = 0;while(bfs(s, e))mx_flw += dfs(s, e, INF);return mx_flw;
}void init()
{k = -1;memset(head, -1, sizeof(head));
}int main()
{ios::sync_with_stdio(false); cin.tie(0);//freopen("T.txt","r",stdin);int s,e;cin >> n >> m >> s >> e;init();int u,v;ll w;for(int i = 1; i <= m; i ++)cin >> u >> v >> w, Add(u, v, w);cout << Dinic(s, e);return 0;
}

题解三(ISAP)

#include<iostream>
#include<algorithm>
#include<queue>
#include<cstring>
using namespace std;#define INF 1e9
const int maxn = 10005;
const int maxm = 200005;
int n, m, s, e;
int k;struct Edge
{int v,w,next;
} edge[2 * maxm];int head[maxn],cur[maxn],deep[maxn];
int last[maxm];
int num[maxm];      // num 桶,用来统计每个分层的节点的数量void Add(int u, int v, int w)
{edge[++ k] = (Edge){ v, w, head[u]};head[u] = k;edge[++ k] = (Edge){ u, 0, head[v]};head[v] = k;
}//bfs 用于更新deep层
void bfs(int e)
{//    for(int i = 0; i <= n; i ++)
//        cur[i] = head[i], deep[i] = n;for(int i = 0; i <= m; i ++) cur[i] = head[i];for(int i = 1; i <= n; i ++) deep[i] = n;deep[e] = 0;queue<int> q;q.push(e);int u, v, w;while(! q.empty()){u = q.front(); q.pop();for(int i = head[u]; i != -1; i = edge[i].next){v = edge[i].v;if(edge[i^1].w && deep[v] == n)      //正图 边存在 且 v这个节点没有被求过{deep[v] = deep[u] + 1;q.push(v);}}}
}int Add_flow(int s, int e)
{int ans = INF;int now = e;while(now != s){ans = min(ans, edge[last[now]].w);now = edge[last[now]^1].v;}now = e;while(now != s){edge[last[now]].w -= ans;edge[last[now]^1].w += ans;now = edge[last[now]^1].v;}return ans;
}int isap(int s, int e)
{int now = s;    //从起点开始进行操作bfs(e);         //先找出来一条边 被操作的增光路for(int i = 1; i <= n; i ++) num[deep[i]] ++;int mx_flw = 0;while(deep[s] < n){if(now == e)        //如果到达汇点直接增广,重新回到源点进行下一轮增广{mx_flw += Add_flow(s, e);now = s;}bool has_find = 0;for(int i = cur[now]; i != -1; i = edge[i].next){if(edge[i].w && deep[now] == deep[edge[i].v] + 1){has_find = 1;   //做标记已经找到一种可行路径cur[now] = i;     //优化当前弧now = edge[i].v;last[edge[i].v] = i;break;}}if(! has_find){int minn = n - 1;for(int i = head[now]; i != -1; i = edge[i].next)if(edge[i].w)minn = min(minn, deep[edge[i].v]);if( (-- num[deep[now]]) == 0) break;   //gap 优化出现了断层num[deep[now] = minn + 1] ++;cur[now] = head[now];if(now != s)now = edge[last[now]^1].v;}}return mx_flw;
}void init()
{k = -1;memset(head, -1, sizeof(head));
}int main()
{ios::sync_with_stdio(false); cin.tie(0);//freopen("T.txt","r",stdin);cin >> n >> m >> s >> e;init();int u,v,w;for(int i = 1; i <= m; i ++)cin >> u >> v >> w, Add(u, v, w);cout << isap(s, e);return 0;
}

P3376 【模板】网络最大流( Edmonds-krap、Dinic、ISAP 算法)相关推荐

  1. 【ybt金牌导航3-2-1】【luogu P3376】网络最大流【Dinic算法】

    网 络 最 大 流 网络最大流 网络最大流 题目链接:ybt金牌导航3-2-1 / luogu P3376 题目 如题,给出一个网络图,以及其源点和汇点,求出其网络最大流. 输入 第一行包含四个正整数 ...

  2. [Luogu] P3376 模板-网络流-最大流

    题目描述 如题,给出一个网络图,以及其源点和汇点,求出其网络最大流. 输入输出格式 输入格式: 第一行包含四个正整数N.M.S.T,分别表示点的个数.有向边的个数.源点序号.汇点序号. 接下来M行每行 ...

  3. 【洛谷P3376】网络最大流【网络流】

    分析 网络流算法本身是之前学过的,今天拿出来复习打个板子. 最原始的思路应该是搜索每一条路,每次进行增广的操作,知道不能增广为止.显然,这种思路复杂度比较高. 如何进行优化?就是dinic算法.上面那 ...

  4. 网络最大流的三种基础算法

    #include<iostream> #include<cstring> #include<queue> #include<cstdio> #inclu ...

  5. 网络流之最大流 EK/Dinic/Isap算法 学习笔记

    EK 算法流程 不停地找增广路进行增广,知道找不到增广路为止. 每一次bfs只找一条增广路. 时间复杂度O(VE2)O(VE^2) 代码 // codevs 1993 #include<iost ...

  6. 最大流ISAP算法模板

    这两天学习了最大流,下面是ISAP算法模板: const int inf = 0x3fffffff; template <int N, int M> struct Isap {int to ...

  7. Dinic最大流 || Luogu P3376 【模板】网络最大流

    题面:[模板]网络最大流 代码: 1 #include<cstring> 2 #include<cstdio> 3 #include<iostream> 4 #de ...

  8. 【网络流】解题报告:luogu P3376 【模板】网络最大流

    题目链接: P3376 [模板]网络最大流 Dinic Dinic算法是网络流最大流的优化算法之一,每一步对原图进行分层,然后用DFS求增广路.时间复杂度是O(n^2*m),Dinic算法最多被分为n ...

  9. 洛谷P3376 【模板】网络最大流

    P3376 [模板]网络最大流 题目描述 如题,给出一个网络图,以及其源点和汇点,求出其网络最大流. 输入输出格式 输入格式: 第一行包含四个正整数N.M.S.T,分别表示点的个数.有向边的个数.源点 ...

  10. 【洛谷 - P3376 】【模板】网络最大流

    题干: 如题,给出一个网络图,以及其源点和汇点,求出其网络最大流. 输入输出格式 输入格式: 第一行包含四个正整数N.M.S.T,分别表示点的个数.有向边的个数.源点序号.汇点序号. 接下来M行每行包 ...

最新文章

  1. List,Set,Collection,Collections比较
  2. 三: cocos2d-x代码分析
  3. 新书发布《每天5分钟玩转Docker容器技术》
  4. 初试Windows 8 RTM
  5. Vue + Element UI——侧边栏LOGO设计DEMO
  6. 为什么网页背景图片都切开
  7. 服务器日志记录_5种改善服务器日志记录的技术
  8. Google Maps Android API v2 (2)- 地图对象
  9. SPFA - Luogu 3385 【模板】负环
  10. 精简版oracle客户端程序
  11. Linux:什么是 i386、i586、 i686、noarch?
  12. 复联4定档 4.24——十一年21部漫威电影,用数据为你梳理口碑、票房、主演最佳......
  13. 激情巴布部落畅快一日游
  14. Python入门(10)——宝可梦数据集探索
  15. 响应式编程之一:概述
  16. sublimelinter php 语法不起作用,sublime安装插件sublimeLinter不起作用解决办法
  17. MDF和DHF、DMR、DHR三者差异?注册与备案文件?
  18. Vue中的深坑——component和components
  19. 时间的过客怎么用计算机完整版,抖音时间的过客MC名决在哪看?附歌词完整版原文...
  20. 《数字集成电路物理设计——陈春章》学习笔记

热门文章

  1. 小程序自动定位当前位置
  2. Web 开发权威指南
  3. Word文档标题编号调整
  4. 传递组播与广播帧:数据待传指示传递信息(DTIM)
  5. 台式计算机时间不能同步,电脑时间同步不了怎么办
  6. 江苏自考计算机专业,2021年江苏自考本科专业选择:计算机类专业前景如何?有哪些科目?...
  7. 有关古希腊罗马神话与医学术语的联系的英文文献去哪找?
  8. 苹果x人脸识别突然失灵_iPhone手机触摸屏失灵怎么办?成都苹果维修点教你轻松解决...
  9. 《云计算技术与应用基础》课程标准
  10. 家庭网络拓扑结构示意图