• 网络最大流EK算法


    题目描述

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

    输入输出格式

    输入格式:

    第一行包含四个正整数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。

        EK和FF的区别在于EK求任意路径是用的是BFS,而FF是DFS,所以不得不说EK比FF快太多了。

        (Dinic和ISAP:两个骑三轮的有什么好比的)

        但EK的思路还是一样的,这里不再细讲。

    #include<set>
    #include<map>
    #include<queue>
    #include<cmath>
    #include<cstdio>
    #include<vector>
    #include<cstring>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    #define INF 2147483647
    using namespace std;
    int read(){
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    struct edge{
        int next,to,head,b;
    }f[440000];
    int n,m,s,t,tot;
    int a[20000],pre[440000],path[440000];
    long long ans;
    void add(int u,int v,int w){
        f[tot].next=f[u].head;f[u].head=tot;f[tot].b=w;f[tot].to=v;tot++;
    }
    void EK(){
        ans=0;
        for(;;){
            memset(a,0,sizeof(a));
            memset(pre,0,sizeof(pre));
            memset(path,0,sizeof(path));
            queue<int> Q; Q.push(s);
            a[s]=INF;
            while(!Q.empty()){
                int x=Q.front(); Q.pop();
                for(int i=f[x].head;i!=-1;i=f[i].next){
                    int p=f[i].to;
                    if(a[p]!=0||!f[i].b) continue;
                    a[p]=min(a[x],f[i].b);
                    pre[p]=x; path[p]=i;
                    Q.push(p);
                }
                if(a[t]) break;
            }
            if(!a[t]) return;
            ans+=a[t];
            for(int i=t;i!=s;i=pre[i]){
                int x=path[i];
                f[x].b-=a[t];
                f[x^1].b+=a[t];
            }
        }
    }
    int main(){
        n=read();m=read();s=read();t=read();
        for(int i=1;i<=n;++i) f[i].head=-1;
        for(int i=1;i<=m;++i){
            int x,y,w;x=read();y=read();w=read();
            add(x,y,w);add(y,x,0);
        }
        EK();
        printf("%lld",ans);
        return 0;
    }
    
    //https://www.luogu.org/problem/show?pid=3376#sub
  • 相关阅读:
    Unity The Method Signature Matching Rule
    Unity The Property Matching Rule
    Unity The Type Matching Rule
    Unity The Custom Attribute Matching Rule
    Unity The Member Name Matching Rule
    Unity No Policies
    Unity The Return Type Matching Rule
    Unity The Parameter Type Matching Rule
    Unity The Namespace Matching Rule
    关于TSQL递归查询的(转)
  • 原文地址:https://www.cnblogs.com/hanyu20021030/p/6567982.html
Copyright © 2020-2023  润新知