P3376 【模板】网络最大流

   https://www.luogu.com.cn/problem/P3376

#include<bits/stdc++.h>
#define int long long
const int INF = 0x3f3f3f3f;
const int maxn = 3e5+10;
using namespace std;
int m,u,w,v;
struct edge {
    int v, c, nxt;
} e[maxn<<1];
int s,t,n,head[maxn],q[maxn],level[maxn],tot;
void add_edge(int u, int v, int c){
    e[tot] = (edge){ v, c, head[u] };
    head[u] = tot++;
}
//分层图
bool BFS(){
    memset(level,0, sizeof(level));
    q[1] = s;
    level[s] = 1;
    int hd = 0,tl = 1;
    while (hd !=  tl){
        hd++;
        for(int i = head[q[hd]]; i != -1; i = e[i].nxt){
            if(e[i].c && !level[e[i].v]){
                tl++;
                level[e[i].v] = level[q[hd]] + 1;
                q[tl] = e[i].v;
                if (e[i].v == t)
                    return true;
            }
        }
    }
    return false;
}

//增广路
int DFS(int f, int u){
    if (u == t)
        return f;
    int d = 0, used = 0;
    for (int i = head[u];i != -1;i = e[i].nxt){
        if (e[i].c && level[u] == level[e[i].v] - 1){
            if ((d = DFS(min(f - used, e[i].c), e[i].v))){
                e[i].c -= d;
                e[i ^ 1].c += d;//建立反向边
                used += d;//这个点的最大流量
            }
        }
    }
    if (!used)
        level[u] = 0;
    return used;
}
int Dinic(){
    int max_flow = 0;
    while(BFS()){//判断汇点层次
        int d = 0;
        while ((d = DFS(INF, s)))
            max_flow += d;
    }
    return max_flow;
}
signed main(){
    //freopen("in","r",stdin);
    ios::sync_with_stdio(0);
    cin >> n >> m >> s >> t;
    memset(head, -1, sizeof(head));
    for (int i = 1; i <= m; i++){
        cin >> u >> v >> w;
        add_edge(u, v, w);
        add_edge(v, u, 0);//为什么是0?
    }
    cout << Dinic() << endl;
    return 0;
}
View Code

 

1、裸的最大流

     2、二分图的最大匹配:建一个点S,连到二分图的集合A中;建一个点T,连到二分图的集合B中。再将所有的集合A中的点与集合B中的点相连。全部边权设为1,跑一遍最大流,结果即为二分图的最大匹配

     3、最小割:在单源单汇流量图中,最大流等于最小割

     4、求最大权闭合图:最大权值=正点权之和-最小割

 


posted @ 2019-07-26 15:54  Hazelxcf  阅读(131)  评论(0编辑  收藏  举报