zoukankan      html  css  js  c++  java
  • LibreOJ #101. 最大流

    题目描述

    这是一道模板题。

    给定 n nn 个点,m mm 条边,给定每条边的容量,求从点 s ss 到点 t tt 的最大流。

    输入格式

    第一行四个整数 n nn、m mm、s ss、t tt。
    接下来的 m mm 行,每行三个整数 u uu、v vv、c cc,表示 u uu 到 v vv,流量为 c cc 的一条边。

    输出格式

    输出点 s ss 到点 t tt 的最大流。

    样例

    样例输入

    7 14 1 7
    1 2 5
    1 3 6
    1 4 5
    2 3 2
    2 5 3
    3 2 2
    3 4 3
    3 5 3
    3 6 7
    4 6 5
    5 6 1
    6 5 1
    5 7 8
    6 7 7

    样例输出

    14

    数据范围与提示

    1≤n≤106,1≤m≤4×106,0≤c≤231−1 1 leq n leq 10 ^ 6, 1 leq m leq 4 imes 10 ^ 6, 0 leq c leq 2 ^ {31} - 11n106​​,1m4×106​​,0c231​​1

    模板题,需要当前弧优化

    屠龙宝刀点击就送

    #include <cstring>
    #include <vector>
    #include <cstdio>
    #include <queue>
    #define N 4000005
    using namespace std;
    struct node
    {
        int to,next,dis;
    }edge[N*2];
    int tot=1,Answer,dis[1000005],head[1000005],n,m,s,t,i,j;
    void add(int from,int to,int w)
    {
        tot++;
        edge[tot].next=head[from];
        edge[tot].to=to;
        edge[tot].dis=w;
        head[from]=tot;
    }
    bool bfs()
    {
        queue<int>q;
        memset(dis,-1,sizeof(dis));
        dis[s]=0;
        q.push(s);
        while(!q.empty() )
        {
            int Top=q.front() ;
            q.pop() ;
            for(i=head[Top];i;i=edge[i].next)
            {
                if(dis[edge[i].to]==-1&&edge[i].dis>0)
                {
                    dis[edge[i].to]=dis[Top]+1;
                    if(edge[i].to==t) return 1;
                    else q.push(edge[i].to); 
                }
            }
        }
        return 0;
    }
    int work(int now,int f)
    {
        if(now==t||f==0) return f;
        int rest=0;
        for(int i=head[now];i;i=edge[i].next)
        {
            int v=edge[i].to;
            if(edge[i].dis>0&&dis[v]==dis[now]+1)
            {
                int t=work(v,min(f,edge[i].dis));
                rest+=t;
                f-=t;
                edge[i].dis-=t;
                edge[i^1].dis+=t;
                if(f==0) return rest;
            }
        }
        if(rest!=f) dis[now]=-1;
        return rest;
    }
    int main()
    {
        scanf("%d%d%d%d",&n,&m,&s,&t);
        int u,v,l;
        for(i=0;i<m;++i)
        {
            scanf("%d%d%d",&u,&v,&l);
            add(u,v,l);
            add(v,u,0);
        }
        while(bfs()) Answer+=work(s,1e8);
        printf("%d",Answer);
        return 0;
    }
    我们都在命运之湖上荡舟划桨,波浪起伏着而我们无法逃脱孤航。但是假使我们迷失了方向,波浪将指引我们穿越另一天的曙光。
  • 相关阅读:
    c#中out与ref的用法与区别
    一次不该出现的bug
    js弹出蒙版
    foreach中不能修改元素的值
    C#中使用正则表达式来过滤html字符
    细微之处才能显示水平
    js画直线 拓荒者
    XSLT模板转换XML文档 拓荒者
    怪异的JavaScript Date对象 拓荒者
    [转]C++ 笔记点滴 拓荒者
  • 原文地址:https://www.cnblogs.com/ruojisun/p/7161257.html
Copyright © 2011-2022 走看看