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

题目描述

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

输入

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

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

输出

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

样例输入

4 5 4 3
4 2 30
4 3 20
2 3 20
2 1 30
1 3 40

样例输出

50

数据规模:

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

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

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

网络流的模板题。汇总一些增广路算法。(Ford-Fulkerson, Edmond-Karp, Dinic, ISAP)

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <vector>
  5 #include <queue>
  6 using namespace std;
  7
  8 struct edge {
  9     int to,cap,rev;
 10 };
 11
 12 const int maxn=10001, INF=0x7F7F7F7F;
 13 int n,m;
 14 vector <edge> G[maxn+1];
 15
 16 edge make_edge(int to, int cap, int rev) {
 17     edge x;
 18     x.to=to, x.cap=cap, x.rev=rev;
 19     return x;
 20 }
 21
 22 void add_edge(int from, int to, int cap) {
 23     G[from].push_back(make_edge(to,cap,G[to].size()));
 24     G[to].push_back(make_edge(from,0,G[from].size()-1));
 25 }
 26
 27 void init() {
 28     for (int i=1; i<=m; i++) {
 29         int u,v,w;
 30         scanf("%d%d%d",&u,&v,&w);
 31         add_edge(u,v,w);
 32     }
 33 }
 34
 35 namespace Ford_Fulkerson {
 36     bool used[maxn+1];
 37
 38     int dfs(int x, int t, int f) {
 39         if (x==t) return f;
 40         used[x]=true;
 41         for (int i=0; i<G[x].size(); i++) {
 42             edge &e=G[x][i];
 43             if (!used[e.to]&&e.cap>0) {
 44                 int d=dfs(e.to,t,min(f,e.cap));
 45                 if (d>0) {
 46                     e.cap-=d;
 47                     G[e.to][e.rev].cap+=d;
 48                     return d;
 49                 }
 50             }
 51         }
 52         return 0;
 53     }
 54
 55     int max_flow(int s, int t) {
 56         int flow=0;
 57         for(;;) {
 58             memset(used,0,sizeof(used));
 59             int f=dfs(s,t,INF);
 60             if (f==0) return flow;
 61             flow+=f;
 62         }
 63     }
 64 }
 65
 66 namespace Edmond_Karp {
 67     bool vis[maxn+1];
 68     int prev[maxn+1];
 69     int pree[maxn+1];
 70
 71     void bfs(int s) {
 72         memset(vis,0,sizeof(vis));
 73         memset(prev,-1,sizeof(prev));
 74         memset(pree,-1,sizeof(prev));
 75         queue <int> q;
 76         vis[s]=true;
 77         q.push(s);
 78
 79         while(!q.empty()) {
 80             int x=q.front();
 81             q.pop();
 82             for (int i=0; i<G[x].size(); i++) {
 83                 edge &e=G[x][i];
 84                 if (e.cap>0&&!vis[e.to]) {
 85                     prev[e.to]=x;
 86                     pree[e.to]=i;
 87                     vis[e.to]=true;
 88                     q.push(e.to);
 89                 }
 90             }
 91         }
 92     }
 93
 94     int max_flow(int s, int t) {
 95         int flow=0;
 96         for(;;) {
 97             bfs(s);
 98             if (!vis[t]) return flow;
 99             int d=INF;
100             for (int i=t; prev[i]!=-1; i=prev[i])
101                 d=min(d,G[prev[i]][pree[i]].cap);
102             for (int i=t; prev[i]!=-1; i=prev[i]) {
103                 edge &e=G[prev[i]][pree[i]];
104                 e.cap-=d;
105                 G[e.to][e.rev].cap+=d;
106             }
107             flow+=d;
108         }
109     }
110 }
111
112 namespace Dinic {
113     int level[maxn+1];
114     int iter[maxn+1];
115
116     void bfs(int s) {
117         memset(level,-1,sizeof(level));
118         queue <int> q;
119         level[s]=0;
120         q.push(s);
121
122         while (!q.empty()) {
123             int x=q.front();
124             q.pop();
125             for (int i=0; i<G[x].size(); i++) {
126                 edge &e=G[x][i];
127                 if (e.cap>0&&level[e.to]<0) {
128                     level[e.to]=level[x]+1;
129                     q.push(e.to);
130                 }
131             }
132         }
133     }
134
135     int dfs(int x, int t, int f) {
136         if (x==t) return f;
137         for (int &i=iter[x]; i<G[x].size(); i++) {
138             edge &e=G[x][i];
139             if (e.cap>0&&level[e.to]>level[x]) {
140                 int d=dfs(e.to,t,min(f,e.cap));
141                 if (d>0) {
142                     e.cap-=d;
143                     G[e.to][e.rev].cap+=d;
144                     return d;
145                 }
146             }
147         }
148         return 0;
149     }
150
151     int max_flow(int s, int t) {
152         int flow=0;
153         for(;;) {
154             bfs(s);
155             if (level[t]<0) return flow;
156             memset(iter,0,sizeof(iter));
157             int f;
158             while ((f=dfs(s,t,INF))>0)
159                 flow+=f;
160         }
161     }
162 }
163
164 namespace ISAP {
165     int gap[maxn+1];
166     int iter[maxn+1];
167     int level[maxn+1];
168
169     void bfs(int t) {
170         memset(gap,0,sizeof(gap));
171         memset(level,-1,sizeof(level));
172         queue <int> q;
173         level[t]=1;
174         gap[level[t]]=1;
175         q.push(t);
176
177         while (!q.empty()) {
178             int x=q.front();
179             q.pop();
180             for (int i=0; i<G[x].size(); i++) {
181                 edge &e=G[x][i];
182                 if (level[e.to]<0) {
183                     level[e.to]=level[x]+1;
184                     gap[level[e.to]]++;
185                     q.push(e.to);
186                 }
187             }
188         }
189     }
190
191     int dfs(int x, int s, int t, int f) {
192         if (x==t) return f;
193         int flow=0;
194         for (int &i=iter[x]; i<G[x].size(); i++) {
195             edge &e=G[x][i];
196             if (e.cap>0&&level[x]==level[e.to]+1) {
197                 int d=dfs(e.to,s,t,min(f-flow,e.cap));
198                 e.cap-=d;
199                 G[e.to][e.rev].cap+=d;
200                 flow+=d;
201                 if (f==flow) return f;
202             }
203         }
204
205         gap[level[x]]--;
206         if (gap[level[x]]==0)
207             level[s]=n+1;
208         iter[x]=0;
209         gap[++level[x]]++;
210         return flow;
211     }
212
213     int max_flow(int s, int t) {
214         int flow=0;
215         bfs(t);
216         memset(iter,0,sizeof(iter));
217         while (level[s]<=n)
218             flow+=dfs(s,s,t,INF);
219         return flow;
220     }
221 }
222
223 int main() {
224     int s,t;
225     scanf("%d%d%d%d",&n,&m,&s,&t);
226     init();
227     printf("%d\n",ISAP::max_flow(s,t));
228     return 0;
229 }

原文地址:https://www.cnblogs.com/tweetuzki/p/8413660.html

时间: 2024-12-11 01:07:50

洛谷 P3376 【【模板】网络最大流】的相关文章

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

P3376 [模板]网络最大流 题目描述 如题,给出一个网络图,以及其源点和汇点,求出其网络最大流. 输入输出格式 输入格式: 第一行包含四个正整数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

洛谷 P3376 【模板】网络最大流 题解

此文为博主原创题解,转载时请通知博主,并把原文链接放在正文醒目位置. 题目链接:https://www.luogu.org/problemnew/show/3376 题目描述 如题,给出一个网络图,以及其源点和汇点,求出其网络最大流. 输入输出格式 输入格式: 第一行包含四个正整数N.M.S.T,分别表示点的个数.有向边的个数.源点序号.汇点序号. 接下来M行每行包含三个正整数ui.vi.wi,表示第i条有向边从ui出发,到达vi,边权为wi(即该边最大流量为wi) 输出格式: 一行,包含一个正

【C++】最近公共祖先LCA(Tarjan离线算法)&amp;&amp; 洛谷P3379LCA模板

1.前言 首先我们介绍的算法是LCA问题中的离线算法-Tarjan算法,该算法采用DFS+并查集,再看此算法之前首先你得知道并查集(尽管我相信你如果知道这个的话肯定是知道并查集的),Tarjan算法的优点在于相对稳定,时间复杂度也比较居中,也很容易理解(个人认为). 2.思想 下面详细介绍一下Tarjan算法的思想: 1.任选一个点为根节点,从根节点开始. 2.遍历该点u所有子节点v,并标记这些子节点v已被访问过. 3.若是v还有子节点,返回2,否则下一步. 4.合并v到u上. 5.寻找与当前点

AC自动机(附洛谷P3769模板题)

首先,介绍一下AC自动机(Aho-Corasick automaton),是一种在一个文本串中寻找每一个已给出的模式串的高效算法. 在学习AC自动机之前,你需要先学习Trie树和KMP算法,因为AC自动机正式利用并结合了两者的思想. 说到实际的不同,其实AC自动机只是在Trie树上引入了一个类似KMP中next数组的东西叫做Fail指针. 对于每一个节点,Fail指针指向该节点所代表的字符串中,次长的.在Trie树中存在的后缀(因为最长的在Trie树种存在的后缀就是其本身)所代表的节点. 举例:

洛谷P3375 [模板]KMP字符串匹配

To 洛谷.3375 KMP字符串匹配 题目描述 如题,给出两个字符串s1和s2,其中s2为s1的子串,求出s2在s1中所有出现的位置. 为了减少骗分的情况,接下来还要输出子串的前缀数组next.如果你不知道这是什么意思也不要问,去百度搜[kmp算法]学习一下就知道了. 输入输出格式 输入格式: 第一行为一个字符串,即为s1(仅包含大写字母) 第二行为一个字符串,即为s2(仅包含大写字母) 输出格式: 若干行,每行包含一个整数,表示s2在s1中出现的位置 接下来1行,包括length(s2)个整

洛谷.3803.[模板]多项式乘法(FFT)

题目链接:洛谷.LOJ. FFT相关:快速傅里叶变换(FFT)详解.FFT总结.从多项式乘法到快速傅里叶变换. #include <cmath> #include <cctype> #include <cstdio> #include <algorithm> #define gc() getchar() const int N=1e6+5; const double PI=acos(-1); int n,m; struct Complex { double

洛谷.1919.[模板]A乘B Problem升级版(FFT)

题目链接:洛谷.BZOJ2179 //将乘数拆成 a0*10^n + a1*10^(n-1) + ... + a_n-1的形式 //可以发现多项式乘法就模拟了竖式乘法 所以用FFT即可 注意处理进位 //n位*n位最多就只有2n位了 //论putchar的速度..还是快的 #include <cmath> #include <cstdio> #include <cctype> #include <algorithm> #define gc() getchar

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

之前的Dinic模板照着刘汝佳写的vector然后十分鬼畜跑得奇慢无比,虽然别人这样写也没慢多少但是自己的就是令人捉急. 改成邻接表之后快了三倍,虽然还是比较慢但是自己比较满意了.虽然一开始ecnt从0开始WA了一发... 之前的码风也十分鬼畜呀缩进只缩1.2格不懂自己怎么想的.. 反正今天就安心划划水. #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #in

[洛谷P3376]【模板】网络最大流

题目大意:略. 解题思路:最大流木板题,以下是Dinic算法的代码. C++ Code: #include<stdio.h> #include<cctype> #include<vector> #include<algorithm> #include<cstring> #include<queue> using namespace std; #define INF 0x3f3f3f3f char buf[40000020]; int