Problem Portal

Portal1:Luogu

Description

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

Input

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

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

Output

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

Sample Input

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

Sample Output

50

Hint

数据规模:

对于\(30\%\)的数据:\(N \leq 10,M \leq 25\);

对于\(70\%\)的数据:\(N \leq 200,M \leq 1000\);

对于\(100\%\)的数据:\(N \leq 10000,M \leq 100000\)。

样例说明:

题目中存在\(3\)条路径:

\(4 \to 2 \to 3\),该路线可通过\(20\)的流量

\(4 \to 3\),可通过\(20\)的流量

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

故流量总计\(20+20+10=50\),输出\(50\)。

Solution

模板题,求最大流。

Code

Emonds Karp(EK)算法
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue> using namespace std; const int INF=0x3f3f3f3f, MAXN=10005, MAXM=200005;
int n, m, s, t, u, v, val, cnt, head[MAXN], dis[MAXN], pre[MAXN];
queue<int> Q;
struct node {
int u, v, val, flow, nxt;
} edge[MAXM];
inline void addedge(int u, int v, int w) {//前向星存图
edge[++cnt].u=u; edge[cnt].v=v; edge[cnt].val=w; edge[cnt].nxt=head[u]; head[u]=cnt;
}
inline bool Emonds_Karp() {
memset(pre, 0, sizeof(pre));
memset(dis, 0, sizeof(dis));//初始化
dis[s]=INF;
pre[s]=0;
Q.push(s);
while(!Q.empty()) {//类似于SPFA
int x=Q.front();
Q.pop();
for (int i=head[x]; i; i=edge[i].nxt) {
int v=edge[i].v;
if (!dis[v] && edge[i].val>edge[i].flow) {
Q.push(v);
dis[v]=min(dis[x], edge[i].val-edge[i].flow);
pre[v]=i;
}
if (dis[t]) break;
}
}
return dis[t];
}
int main() {
scanf("%d%d%d%d",&n, &m, &s, &t);
cnt=1;
for(int i=1; i<=m; i++) {
scanf("%d%d%d",&u, &v, &val);
addedge(u, v, val);
addedge(v, u, 0);//前向星存图
}
int ans=0;
while (Emonds_Karp()) {//Emonds Karp算法
for (int i=t; i!=s; i=edge[pre[i]].u) {
edge[pre[i]].flow+=dis[t];
edge[pre[i] xor 1].val-=dis[t];
}
ans+=dis[t];
}
printf("%d\n",ans);
return 0;
}
Dinic算法
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue> using namespace std; const int INF=0x3f3f3f3f, MAXN=10005, MAXM=200005;
struct node {
int nxt, to, val;
} edge[MAXM];
queue<int> Q;
int n, m, s, t, u, v, cnt, val, dis[MAXN], head[MAXN];
inline void addedge(int u, int v, int w) {//前向星存图
edge[++cnt].val=w; edge[cnt].to=v; edge[cnt].nxt=head[u]; head[u]=cnt;
}
inline bool bfs() {
memset(dis, -1, sizeof(dis));
dis[s]=0;
Q.push(s);
while (!Q.empty()) {
int x=Q.front();
Q.pop();
for (int i=head[x]; ~i; i=edge[i].nxt) {
int v=edge[i].to;
if (edge[i].val && dis[v]==-1) {
dis[v]=dis[x]+1;
Q.push(v);
}
}
}
if (~dis[t]) return 1;
return 0;
}
inline int dfs(int u, int flow) {
if (u==t) return flow;
int ret=flow;
for (int i=head[u]; ~i; i=edge[i].nxt) {
if (ret<=0) break;
int v=edge[i].to;
if (edge[i].val && dis[v]==dis[u]+1) {
int x=dfs(v, min(edge[i].val, ret));
ret-=x;
edge[i].val-=x;
edge[i xor 1].val+=x;
}
}
return flow-ret;
}
inline int Dinic() {//Dinic算法
int ret=0;
while (bfs()) ret+=dfs(s, INF);
return ret;
}
int main() {
scanf("%d%d%d%d",&n, &m, &s, &t);
memset(head, -1, sizeof(head));
cnt=1;
for (int i=1; i<=m; i++) {
scanf("%d%d%d",&u, &v, &val);
addedge(u, v, val);
addedge(v, u, 0);//双边
}
printf("%d\n",Dinic());
return 0;
}
Improved Shortest Augmenting Path(ISAP)算法
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue> using namespace std; const int INF=0x3f3f3f3f, MAXN=10005, MAXM=200005;
queue<int> Q;
int n, m, s, t, u, v, val, cnt, ans, head[MAXN], head1[MAXN], deep[MAXN], pre[MAXN], a[MAXN];
struct node {
int v, w, nxt;
} edge[MAXM];
inline void addedge(int u, int v, int w) {//前向星存图
edge[cnt].v=v; edge[cnt].w=w; edge[cnt].nxt=head[u]; head[u]=cnt++;
}
inline void bfs(int t) {
for (int i=1; i<=n; i++)
head1[i]=head[i];
for (int i=1; i<=n; i++)
deep[i]=n;
deep[t]=0;
Q.push(t);
while (!Q.empty()) {
int u=Q.front();
Q.pop();
for (int i=head[u]; ~i; i=edge[i].nxt)
if (deep[edge[i].v]==n && edge[i^1].w) {
deep[edge[i].v]=deep[u]+1;
Q.push(edge[i].v);
}
}
}
int calc(int s,int t) {//计算
int ans=INF, u=t;
while (u!=s) {
ans=min (ans,edge[pre[u]].w);
u=edge[pre[u] xor 1].v;
}
u=t;
while (u!=s) {
edge[pre[u]].w-=ans;
edge[pre[u] xor 1].w+=ans;
u=edge[pre[u] xor 1].v;
}
return ans;
}
inline void ISAP(int s, int t) {//ISAP算法
int u=s;
bfs(t);
for (int i=1; i<=n; i++)
a[deep[i]]++;
while (deep[s]<n) {
if (u==t) {
ans+=calc(s, t);
u=s;
}
bool flag=0;
for (int &i=head1[u]; ~i; i=edge[i].nxt)
if (deep[u]==deep[edge[i].v]+1 && edge[i].w) {
flag=1;
u=edge[i].v;
pre[edge[i].v]=i;
break;
}
if (!flag) {
int Min=n-1;
for (int i=head[u]; ~i; i=edge[i].nxt)
if (edge[i].w) Min=min(Min, deep[edge[i].v]);
if ((--a[deep[u]])==0) break;
a[deep[u]=Min+1]++;
head1[u]=head[u];
if (u!=s) u=edge[pre[u] xor 1].v;
}
}
}
int main() {
memset(head, -1, sizeof (head));
scanf("%d%d%d%d",&n, &m, &s, &t);
for (int i=1; i<=m; i++) {
scanf("%d%d%d",&u, &v, &val);
addedge(u, v, val);
addedge(v, u, 0);//双边
}
ISAP(s, t);
printf ("%d\n",ans);
return 0;
}

『题解』洛谷P3376 【模板】网络最大流的更多相关文章

  1. 『题解』洛谷P1063 能量项链

    原文地址 Problem Portal Portal1:Luogu Portal2:LibreOJ Portal3:Vijos Description 在\(Mars\)星球上,每个\(Mars\)人 ...

  2. 『题解』洛谷P3384 【模板】树链剖分

    Problem Portal Portal1: Luogu Description 如题,已知一棵包含\(N\)个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作\(1\): ...

  3. 『题解』洛谷P1993 小K的农场

    更好的阅读体验 Portal Portal1: Luogu Description 小\(K\)在\(\mathrm MC\)里面建立很多很多的农场,总共\(n\)个,以至于他自己都忘记了每个农场中种 ...

  4. 『题解』洛谷P2296 寻找道路

    更好的阅读体验 Portal Portal1: Luogu Portal2: LibreOJ Description 在有向图\(\mathrm G\)中,每条边的长度均为\(1\),现给定起点和终点 ...

  5. 『题解』洛谷P1351 联合权值

    更好的阅读体验 Portal Portal1: Luogu Portal2: LibreOJ Description 无向连通图\(\mathrm G\)有\(n\)个点,\(n - 1\)条边.点从 ...

  6. 『题解』洛谷P2170 选学霸

    更好的阅读体验 Portal Portal1: Luogu Description 老师想从\(N\)名学生中选\(M\)人当学霸,但有\(K\)对人实力相当,如果实力相当的人中,一部分被选上,另一部 ...

  7. 『题解』洛谷P1083 借教室

    更好的阅读体验 Portal Portal1: Luogu Portal2: LibreOJ Portal3: Vijos Description 在大学期间,经常需要租借教室.大到院系举办活动,小到 ...

  8. 『题解』洛谷P1314 聪明的质监员

    更好的阅读体验 Portal Portal1: Luogu Portal2: LibreOJ Portal3: Vijos Description 小T是一名质量监督员,最近负责检验一批矿产的质量.这 ...

  9. 『题解』洛谷P2357 守墓人

    Portal Portal1: Luogu Description 在一个荒凉的墓地上有一个令人尊敬的守墓人,他看守的墓地从来没有被盗过, 所以人们很放心的把自己的先人的墓安顿在他那守墓人能看好这片墓 ...

随机推荐

  1. 从0开始学FreeRTOS-(创建任务)-2

    # 补充 开始今天的内容之前,先补充一下上篇文章[从单片机到操作系统-1](https://jiejietop.gitee.io/freertos-1/)的一点点遗漏的知识点. ```js BaseT ...

  2. 02-19 k近邻算法(鸢尾花分类)

    [TOC] 更新.更全的<机器学习>的更新网站,更有python.go.数据结构与算法.爬虫.人工智能教学等着你:https://www.cnblogs.com/nickchen121/ ...

  3. B-线性代数-距离公式汇总

    目录 距离公式汇总 一.欧式距离 二.曼哈顿距离 三.闵可夫斯基距离(Minkowski distance) 更新.更全的<机器学习>的更新网站,更有python.go.数据结构与算法.爬 ...

  4. 微信小程序模板消息

    1 先去微信公众平台,选择现有模板,会有一个模板编号,模板中没有的关键词,可以申请新增. 微信公众平台直达:https://mp.weixin.qq.com 模板消息对应文档直达:https://de ...

  5. 一张图一个题帮你迅速理解RLU算法

    下面是某年的软考题: 某进程页面访问序列为4,2,3,1,2,4,5,3,1,2,3,5,且开始执行时内存中没有页面,分配给该进程的物理块数是3,则采用RLU页面置换算法时的缺页率是多少? 对于这个问 ...

  6. Windows系统调用中API从3环到0环(下)

     Windows内核分析索引目录:https://www.cnblogs.com/onetrainee/p/11675224.html Windows系统调用中API从3环到0环(下) 如果对API在 ...

  7. [NOIp2014] luogu P2312 解方程

    题目描述 已知方程∑i=0naixi=0\sum_{i=0}^{n}{a_ix^i}=0i=0∑n​ai​xi=0求该方程在 [1,m][1,m][1,m] 内的整数解. Solution 有一个秦九 ...

  8. JedisCluster与keys/scan查找

    最近买了几个专栏,关于算法.JVM.redis,学不过来.主要是身体也不太好,视物光斑转头疼的问题出现越来越频繁.再加上早上起来嗓子痒打喷嚏.很烦. 稍记录一下redis集群的问题: 1.scan在集 ...

  9. 图论-最小生成树<Kruskal>

    昨天: 图论-最小生成树<Dijkstra,Floyd> 以上是昨天的Blog,有需要者请先阅读完以上再阅读今天的Blog. 可能今天的有点乱,好好理理,认真看完相信你会懂得 然而,文中提 ...

  10. Leetcode(10)正则表达式匹配

    Leetcode(10)正则表达式匹配 [题目表述]: 给定一个字符串 (s) 和一个字符模式 (p).实现支持 '.' 和 '*' 的正则表达式匹配. '.' 匹配任意单个字符. '*' 匹配零个或 ...