zoukankan      html  css  js  c++  java
  • 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
    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。

    思路

    Edmonds-Karp:每次从所有的边中寻找一条可增广的路径,将它进行增广,更新最大流。

    代码

    #include<bits/stdc++.h>
    #define N 10700
    #define M 107000
    #define inf 1<<29
    using namespace std;
    struct node{
        int y,z,next;
    }e[M*2];
    int tot=1,head[N],maxflow=0;
    int n,m,s,t;
    void add(int x,int y,int z){
        e[++tot].y=y;e[tot].z=z;e[tot].next=head[x];head[x]=tot;
        e[++tot].y=x;e[tot].z=0;e[tot].next=head[y];head[y]=tot;
    }
    int incf[N],v[N],pre[N];
    bool bfs(){
        memset(v,0,sizeof(v));
        queue<int> q;
        q.push(s);v[s]=1;
        incf[s]=inf;
        while(q.size()){
            int x=q.front();q.pop();
            for(int i=head[x];i;i=e[i].next){
                int y=e[i].y,z=e[i].z;
                if(z){
                    if(v[y]) continue;
                    incf[y]=min(incf[x],z);
                    pre[y]=i;
                    q.push(y);v[y]=1;
                    if(y==t) return 1;
                }
            }
        }
        return 0;
    }
    void update(){
        int x=t;
        while(x!=s){
            int i=pre[x];
            e[i].z-=incf[t];
            e[i^1].z+=incf[t];
            x=e[i^1].y; 
        }
        maxflow+=incf[t];
    }
    int main()
    {
        int x,y,z;
        cin>>n>>m>>s>>t;
        for(int i=1;i<=m;i++){
            scanf("%d%d%d",&x,&y,&z);
            add(x,y,z);
        }
        while(spfa()) update();
        cout<<maxflow<<endl;
        return 0;
    }

    思路

    Dinic:由于E-K算法中需要遍历全图才更新一条,因此我们可以进行分层,将图进行分层后直接增广所有可行边。

    代码

    #include<bits/stdc++.h>
    #define N 10700
    #define M 107000
    #define inf 1<<29
    using namespace std;
    struct node{
        int y,z,next;
    }e[M*2];
    int tot=1,head[N],maxflow=0;
    int n,m,s,t;
    void add(int x,int y,int z){
        e[++tot].y=y;e[tot].z=z;e[tot].next=head[x];head[x]=tot;
        e[++tot].y=x;e[tot].z=0;e[tot].next=head[y];head[y]=tot;
    }
    queue<int> q;
    int d[N];
    bool bfs(){
        memset(d,0,sizeof(d));
        while(q.size()) q.pop();
        q.push(s);d[s]=1;
        while(q.size()){
            int x=q.front();q.pop();
            for(int i=head[x];i;i=e[i].next){
                int y=e[i].y,z=e[i].z;
                if(z&&!d[y]){
                    q.push(y);d[y]=d[x]+1;
                    if(y==t) return 1;
                }
            } 
        }
        return 0;
    }
    int dinic(int x,int flow){
        if(x==t) return flow;
        int rest=flow,k;
        for(int i=head[x];i;i=e[i].next){
            int y=e[i].y,z=e[i].z;
            if(z&&d[y]==d[x]+1){
                k=dinic(y,min(rest,z));
                if(!k) d[y]=0;
                e[i].z-=k;
                e[i^1].z+=k;
                rest-=k; 
            }
        }
        return flow-rest;
    }
    int main()
    {
        int x,y,z,flow=0;
        cin>>n>>m>>s>>t;
        for(int i=1;i<=m;i++){
            scanf("%d%d%d",&x,&y,&z);
            add(x,y,z);
        }
        while(bfs()) 
            while(flow=dinic(s,inf)) maxflow+=flow;
        cout<<maxflow<<endl;
        return 0;
    }
  • 相关阅读:
    玩转html2canvas以及常见问题解决
    docker磁盘空间清理办法
    统计行数、文件夹个数、文件个数的相关shell命令
    golang将字符串进行md5加密
    思考如何将自动化测试加入持续集成中
    锋利的NodeJS之NodeJS多线程
    成年人的必修课:抗压和自驱力
    MacOS下PHP7.1升级到PHP7.4.15
    php性能分析利器:xhprof
    后Low Code时代:聚焦和突破
  • 原文地址:https://www.cnblogs.com/wangyiding2003/p/11524165.html
Copyright © 2011-2022 走看看