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;
}
原文地址:https://www.cnblogs.com/wangyiding2003/p/11524165.html