Jeanny
寂兮,寥兮,独立不改,周行而不殆

0.网络流解释:如果你还是不能理解,我们就换一种说法,假设s城有inf个人想去t城,但是从s到t要经过一些城市才能到达,(以上图为例)其中s到3城的火车票还剩10张,3到t的火车票还剩15张,其他路以此类推,问最终最多能有多少人能到达t城?(假设这个地区只有火车,没有汽车飞机,步行和骑自行车会累死就不考虑了,再假设所有人都买得起火车票。)

1.https://www.cnblogs.com/zsboy/archive/2013/01/27/2878810.html EK 算法 ,但是“反悔”那个图应该9 1 9 1 9 。

2. Dinic算法可以每次找出多条增广路,为什么要分层呢?分层图是有向无环图。

每bfs一次的结果在运行框中。

//在什么情况下用它?
//如何实现?
//最小费用最大流
//最大流的方法,不论走哪条路线,最终都会求出整个图的最大流
#include<cstdio>
#include<iostream>
#include<queue>
#include<cstring>
#include<algorithm>
#define INF 0x7fffffff
#define int long long
using namespace std;
int n,m,s,t,hd[205],cnt = 1, pre[205], f[205], ed[205];
struct Edge{
    int to,nxt,w;
}edge[10005];
void add(int u, int v, int w){
    cnt++;
    edge[cnt].to = v;
    edge[cnt].nxt = hd[u];
    edge[cnt].w = w;
    hd[u] = cnt;
}
int bfs(){
    queue<int> q;
    f[s] = INF;q.push(s);
    memset(pre,-1,sizeof pre);
    while(!q.empty()){
        int u = q.front(); q.pop();
        for(int i = hd[u]; i; i = edge[i].nxt){
            int v = edge[i].to;
            if(edge[i].w > 0 && pre[v] == -1){
                f[v] = min(f[u], edge[i].w);
                pre[v] = u;
                ed[v] = i;//一开始边没有写对
                q.push(v);
                if(v == t) return 1;
            }
        }
    }
    return 0;
}
int ek(){
    int mxflow = 0;
    while(bfs()){
        mxflow += f[t];
        for(int i = t; i != s; i = pre[i]){
            edge[ed[i]].w -= f[t];
            edge[ed[i]^1].w += f[t];
        }
    }
    return mxflow;
}
signed main(){
    scanf("%lld%lld%lld%lld",&n,&m,&s,&t); int u,v,w;
    for(int i = 1; i <= m; i++){
        scanf("%lld%lld%lld",&u,&v,&w);
        add(u,v,w);
        add(v,u,0);
    }
    printf("%lld\n",ek());
    return 0;
}

 dinic

#include<bits/stdc++.h>
#define inf 0x7fffffffffffffff
typedef  long long ll;
using namespace std;
int cnt = 1, hd[205],n,m,s,t,x,y,z,dep[205],cur[205];
ll mxflow;
struct Edge{
    int to,nxt,w;
}edge[10005];
void add(int u, int v, int w){
    cnt++;
    edge[cnt].to = v;
    edge[cnt].nxt = hd[u];
    edge[cnt].w = w;
    hd[u] = cnt;
}
queue<int> q;
int bfs(){
    memset(dep, 0, sizeof dep);
    while(!q.empty()) q.pop();
    q.push(s); dep[s] = 1; cur[s] = hd[s];
    while(!q.empty()){
        int u = q.front(); q.pop();
        for(int i = hd[u]; i; i = edge[i].nxt){
            int v = edge[i].to;
            if(edge[i].w && !dep[v]){
                dep[v] = dep[u] + 1;
                cur[v] = hd[v];
                q.push(v);
                if(v == t) return 1;    
            }
        }    
    }
    return 0;
}
ll dinic(int u, ll flow){//dinic函数表示这点以后的最大流量
    if(u == t) return flow;
    ll res = flow;
    for(int i = cur[u]; i; i = edge[i].nxt){
        cur[u] = i;
        int v = edge[i].to;
        if(res && dep[v] == dep[u] + 1 && edge[i].w){
            int k = dinic(v, min(ll(edge[i].w), res));//res和edge[i].w的最小值,决定往后传的最小值
            if(!k) dep[v] = 0;//我与终点(顺着残量网络)不连通
            edge[i].w -= k;
            edge[i^1].w += k;
            res -= k;
        }
    }
    return flow - res;
}
int main(){
    scanf("%d%d%d%d",&n,&m,&s,&t);
    for(int i = 1; i <= m; i++){
        scanf("%d%d%d",&x,&y,&z);
        add(x,y,z);
        add(y,x,0);
    }
    while(bfs()){
        ll flow = 0;
        while(flow = dinic(s, inf))
            mxflow += flow;
    }
    printf("%lld\n",mxflow);
    return 0;
}

上下界网络流:
https://www.cnblogs.com/verjun/archive/2004/01/13/13154188.html
posted on 2018-06-26 19:53  Jeanny  阅读(171)  评论(0)    收藏  举报