P3376 【模板】网络最大流

【模板】网络最大流

题目描述

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

输入格式

第一行包含四个正整数 n , m , s , t n,m,s,t n,m,s,t,分别表示点的个数、有向边的个数、源点序号、汇点序号。

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

输出格式

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

样例 #1

样例输入 #1

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

样例输出 #1

50

提示

样例输入输出 1 解释

题目中存在 3 3 3 条路径:

  • 4 → 2 → 3 4\to 2\to 3 423,该路线可通过 20 20 20 的流量。
  • 4 → 3 4\to 3 43,可通过 20 20 20 的流量。
  • 4 → 2 → 1 → 3 4\to 2\to 1\to 3 4213,可通过 10 10 10 的流量(边 4 → 2 4\to 2 42 之前已经耗费了 20 20 20 的流量)。

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


数据规模与约定
  • 对于 30 % 30\% 30% 的数据,保证 n ≤ 10 n\leq10 n10 m ≤ 25 m\leq25 m25
  • 对于 100 % 100\% 100% 的数据,保证 1 ≤ n ≤ 200 1 \leq n\leq200 1n200 1 ≤ m ≤ 5000 1 \leq m\leq 5000 1m5000 0 ≤ w < 2 31 0 \leq w\lt 2^{31} 0w<231
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const ll INF=1e9;
int n,m,s,t;
const int N=250, M=11000;              //M定义为边的两倍:双向边
int cnt=1,head[N];                     //8-16行:链式前向星。cnt初值不能是0,可以是1、3、5
struct {int to, nex, w;} e[M];
void add(int u,int v,int w) {
    cnt++;                  //cnt初值是1,cnt++后第一个存储位置是cnt=2,是偶数位置
    e[cnt].to = v;
    e[cnt].w = w;
    e[cnt].nex = head[u];
    head[u] = cnt;
}
int now[N],dep[N];                     //dep[]记录点所在的层次(深度)
int bfs() {                            //在残留网络中构造分层图
    for(int i=1;i<=n;i++) dep[i]=INF;
    dep[s] = 0;                        //从起点s开始分层
    now[s] = head[s];                  //当前弧优化。now是head的拷贝
    queue<int>Q;  Q.push(s);
    while(!Q.empty()) {
        int u = Q.front();   Q.pop();
        for(int i=head[u]; i>0;i=e[i].nex) {   //搜点u的所有邻居,邻居是下一层
            int v = e[i].to;
            if(e[i].w>0 && dep[v]==INF) {      // e[i].w>0表示还有容量
                Q.push(v);
                now[v] = head[v];
                dep[v] = dep[u]+1;             //分层:u的邻居v是u的下一层
                if(v==t) return 1;             //搜到了终点,返回1
            }
        }
    }
    return 0;   //如果通过有剩余容量的边无法到达终点t,即t不在残留网络中,返回0
}
int dfs(int u,ll sum) {                        //sum是这条增广路对最大流的贡献
    if(u==t) return sum;
    ll k,flow=0;                               //k是当前最小的剩余容量
    for(int i=now[u]; i>0 && sum>0; i=e[i].nex) {
        now[u]=i;                              //当前弧优化
       int v=e[i].to;
        if(e[i].w>0 && (dep[v]==dep[u]+1)){   //分层:用dep限制只能访问下一层
            k = dfs(v,min(sum,(ll)e[i].w));
            if(k==0) dep[v] = INF;   //剪枝,去掉增广完毕的点。其实把INF写成0也行
            e[i].w -= k;             //更新残留网络:正向减
            e[i^1].w += k;           //更新残留网络:反向加。小技巧:奇偶边
            flow += k;               //flow表示经过该点的所有流量和
            sum -= k;                //sum表示经过该点的剩余流量
        }
    }
    return flow;
}
int main() {
    scanf("%d%d%d%d",&n,&m,&s,&t);
    for(int i=1;i<=m;i++) {
        int u,v,w;   scanf("%d%d%lld",&u,&v,&w);
        add(u,v,w);  add(v,u,0);      //双向边,反向边的容量是0
    }
    ll ans=0;
    while(bfs()) ans += dfs(s,INF);   //先后做BFS和DFS。当t不在残留网络中时退出
    printf("%lld",ans);
    return 0;
}

  • 25
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Visio是一种流程图和图示软件,包含了各种模板,其中也包括了神经网络模板。神经网络是一种受到生物神经系统启发的计算模型,其目的是模拟人脑处理信息的方式。Visio神经网络模板可以帮助用户图示化和设计神经网络的结构和流程。 Visio神经网络模板提供了各种形状和符号,用于表示神经元、神经网络的层次结构、连接权重、输入和输出等。通过拖动和连接这些形状,用户可以根据自己的需要构建自定义的神经网络模型。而且,Visio还提供了文本框和注释工具,可以添加文字说明和注解,使得神经网络的图示更加清晰明了。 使用Visio神经网络模板,用户可以更好地理解神经网络的结构和运作原理。通过将神经网络可视化,用户可以更直观地看到网络的层次结构、节点之间的连接关系以及信号传递的路径,从而更好地分析和调整神经网络的性能。 此外,Visio还具备一些高级功能,例如自动布局、网格对齐、实时协作等,使得用户能够更轻松地创建复杂的神经网络图。用户可以根据需要自定义颜色、样式和大小等,以及保存或导出图示,与他人共享和交流。 总之,Visio神经网络模板是一个强大的工具,可以帮助用户可视化和设计神经网络。通过这个模板,用户可以更好地理解神经网络,并在设计和优化神经网络时提供有用的辅助功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值