zoukankan      html  css  js  c++  java
  • 【模板】最大流模板(dinic)

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

    输入输出格式
    输入格式:
    第一行包含四个正整数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

    一堆注释掉的中间输出见证了脑残错误的代价QAQ。。。
    code:

    //By Menteur_Hxy
    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<queue>
    using namespace std;
    
    int rd() {
        int x=0,fla=1;
        char c=' ';
        while(c>'9'|| c<'0') {if(c=='-') fla=-fla; c=getchar();}
        while(c<='9'&&c>='0') x=x*10+c-'0',c=getchar();
    //  scanf("%d",&x);
        return x*fla;
    }
    
    const int MAX=10010;
    const int INF=1e9;
    int n,m,s,t,cnt;
    int maxflow;
    int head[MAX],deep[MAX],cur[MAX];
    
    struct edges{
        int to,next,w;
    };
    edges edge[200010];
    
    void add(int x,int y,int z) {
         edge[++cnt].next=head[x];
         edge[cnt].to=y;
         edge[cnt].w=z;
         head[x]=cnt;
    //     cout<<cnt<<" "<<edge[cnt].to<<" "<<edge[cnt].next<<" "<<edge[cnt].w<<endl;
    }
    
    queue <int> q;
    
    bool bfs() {
        memset(deep,0,sizeof deep);
        deep[s]=1;
        for(int i=1;i<=n;i++) cur[i]=head[i];//!!!
        while(!q.empty()) q.pop();
        q.push(s);
    
        while(!q.empty()) {
            int u=q.front(),v; q.pop();
            for(int i=head[u];i!=-1;i=edge[i].next) 
                if(!deep[v=edge[i].to] && edge[i].w) {
                    deep[v]=deep[u]+1;
                    q.push(v);
                }
        }
    //  cout<<deep[t]<<endl;
    //  for(int i=1;i<=n;i++) cout<<deep[i]<<" ";
    //  cout<<endl;
        return deep[t];
    } 
    
    int dfs(int now,int flow) {
        if(now==t) return flow;
    
        for(int& i=cur[now];i!=-1;i=edge[i].next) {
            int v=edge[i].to,di;
    //      if(v==t) cout<<edge[i].w<<endl;
            if(deep[now]+1==deep[v] && edge[i].w 
                && (di=dfs(v,min(flow,edge[i].w))) ) {
    //          if(v==t) cout<<edge[i].w<<endl;
                edge[i].w-=di;
                edge[i^1].w+=di;
                return di;
            }
        }
        return 0;
    }
    
    void dinic() {
        while(bfs())
            while(int di=dfs(s,INF))
                maxflow+=di;
    }
    
    int main() {
        n=rd(),m=rd(),s=rd(),t=rd();
        cnt=-1;
        memset(head,-1,sizeof head);
        for(int i=1;i<=m;i++) {
            int a=rd(),b=rd(),c=rd();
            add(a,b,c);
            add(b,a,0);
        }
        dinic();
        printf("%lld",maxflow);
        return 0;
    }
    版权声明:本文为博主原创文章,未经博主允许不得转载。 博主:https://www.cnblogs.com/Menteur-Hxy/
  • 相关阅读:
    ZOJ2334 Monkey King 并查集 STL
    ZOJ2286 Sum of Divisors 筛选式打表
    ZOJ2105 终于找到错误
    ZOJ-2091-Mean of Subsequence (反证法的运用!!)
    【9929】潜水员
    【9928】混合背包
    【t077】宝物筛选
    【9927】庆功会
    【9926】完全背包
    【9925】0/1背包
  • 原文地址:https://www.cnblogs.com/Menteur-Hxy/p/9247994.html
Copyright © 2011-2022 走看看