最大流

Posted 橘生淮南终洛枳

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了最大流相关的知识,希望对你有一定的参考价值。

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。

代码:

注意:

  边表标号从1开始(因为i^1,一个偶数异或1,是比it大的第一个奇数,一个奇数异或1,是比it小的第一个偶数)

  代码33h   是len[i]而不是len[v]

技术分享优化
技术分享
#include<queue>
#include<cstdio>
#include<iostream>
using namespace std;

const int N = 10010;
const int M = 100010;
int head[N],pre[M*4],to[M*4],len[M*4],num=1,depth[N],cnt[N];
int n,m,s,e,INF=0x7fffffff,ans;
queue<int>q;

void add(int u,int v,int w) {
    pre[++num]=head[u],to[num]=v,len[num]=w,head[u]=num;
    pre[++num]=head[v],to[num]=u,len[num]=0,head[v]=num;
}

bool bfs() {
    for(int i=0; i<=n; i++) {
        cnt[i]=head[i];
        depth[i]=-1;
    }
    while(!q.empty()) q.pop();
    q.push(s);
    depth[s]=0; 
    while(!q.empty()) {
        int now=q.front();
        q.pop();
        for(int i=head[now]; i!=0; i=pre[i]) {
            int v=to[i];
            if(depth[v]==-1 && len[i]>0) {
                q.push(v);
                depth[v]=depth[now]+1;
                if(v==e) return true;
            }
        }
    }
    return false;
}

int dfs(int now,int spend) {
    if(now==e) return spend;
    int new_spend,rest=0;
    for(int & i=cnt[now]; i!=0; i=pre[i]) {
        int v=to[i];
        if(depth[v]==depth[now]+1 && len[i]>0) {
            new_spend=dfs(v,min(len[i],spend-rest));
            if(new_spend) {
                len[i]-=new_spend;
                len[i^1]+=new_spend;
                rest+=new_spend;
                if(rest==spend) break;
            }
        }
    }
    if(rest!=spend) depth[now]=-1;
    return rest; //!!!
}

void dinic() {
    while(bfs()) {
        ans+=dfs(s,INF);
    }
    printf("%d",ans);
}

int main() {
    scanf("%d%d%d%d",&n,&m,&s,&e);
    for(int i=1; i<=m; i++) {
        int u,v,w;
        scanf("%d%d%d",&u,&v,&w);
        add(u,v,w);
    }
    dinic();
    return 0;
}
优化版本

 

 

自己选的路,跪着也要走完!!!

以上是关于最大流的主要内容,如果未能解决你的问题,请参考以下文章

此应用小部件片段中所有意图 (PendingIntents) 的逻辑流

费用流伪代码

是否可以动态编译和执行 C# 代码片段?

从流输入中解析没有根元素的 XML 片段列表

16个必备的JavaScript代码片段

[洛谷P3381]模板最小费用最大流