网络流算法笔记

【例题】
1.POJ Drainage Ditches 【最大流EK算法模板】

#include<cstdio>
#include<string>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<cstring>
#include<set>
#include<queue>
#include<algorithm>
#include<vector>
#include<map>
#include<cctype>
#include<stack>
#include<sstream>
#include<list>
#include<assert.h>
#include<bitset>
#include<numeric>
#define debug() puts("++++")
#define gcd(a,b) __gcd(a,b)
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define fi first
#define se second
#define pb push_back
#define sqr(x) ((x)*(x))
#define ms(a,b) memset(a,b,sizeof(a))
#define sz size()
#define be begin()
#define pu push_up
#define pd push_down
#define cl clear()
#define lowbit(x) -x&x
#define all 1,n,1
#define mod(x) ((x)%M)
#define pi acos(-1.0)
#define rep(i,x,n) for(int i=(x); i<(n); i++)
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> P;
const int INF = 1<<30;
const int maxn = 1e3;
const double eps = 1e-8;
const int dx[] = {-1,1,0,0,1,1,-1,-1};
const int dy[] = {0,0,1,-1,1,-1,1,-1};
int dir[2]={-1,1};
const int mon[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
const int monn[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int s,t,n,m;
inline int read()
{
    int x=0;
    char c=getchar();
    while(c>'9'||c<'0')c=getchar();
    while(c>='0'&&c<='9')x=x*10+c-'0',c=getchar();
    return x;
}
int head[maxn],tot=1;
void init()
{
    ms(head,-1);
    tot=1;
}
struct Pre
{
    int v,edge;//该点的前一个点(从起点过来) 与该点相连的边(靠近起点的)
}pre[maxn];
struct node
{
    int v,w,nxt;
}e[maxn];
void add(int u,int v,int w)
{
    e[++tot].v=v;
    e[tot].w=w;
    e[tot].nxt=head[u];
    head[u]=tot;
}
int vis[maxn];
inline bool bfs()
{
    queue<int> q;
    ms(vis,0);ms(pre,-1);
    vis[s]=1; q.push(s);
    while(!q.empty())
    {
        int u=q.front(); q.pop();
        for(int i=head[u]; i!=-1; i=e[i].nxt)
        {
            int v=e[i].v;
            if(!vis[v]&&e[i].w)
            {
                pre[v].v=u;
                pre[v].edge=i;
                if(v==t) return 1;
                vis[v]=1;
                q.push(v);
            }
        }
    }
    return 0;
}
int ek()
{
    int ans=0;
    while(bfs())
    {
        int mi=INF;
        for(int i=t; i!=s; i=pre[i].v)//每次只能增加增广路上最小的边的权值
        {
            mi = min(mi,e[pre[i].edge].w);
        }
        for(int i=t; i!=s; i=pre[i].v)
        {
            e[ pre[i].edge ].w -= mi;
            e[ pre[i].edge^1 ].w += mi;
        }
        ans += mi;
    }
    return ans;
}
int main()
{

    while(~scanf("%d%d",&m,&n))
    {
        init();
        s=1,t=n;
        int u,v,w;
        for(int i=1;i<=m;i++)
            u=read(),v=read(),w=read(),add(u,v,w),add(v,u,0);
        printf("%d
",ek());
    }
}
/*
【题意】

【类型】最大流EK算法模板

【分析】https://www.luogu.org/blog/ONE-PIECE/wang-lao-liu-di-zong-jie

【时间复杂度&&优化】O(nm^2)(n为点数,m为边数)

【trick】

【数据】

*/

2.洛谷 P3376 【模板】网络最大流

#include<cstdio>
#include<string>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<cstring>
#include<set>
#include<queue>
#include<algorithm>
#include<vector>
#include<map>
#include<cctype>
#include<stack>
#include<sstream>
#include<list>
#include<assert.h>
#include<bitset>
#include<numeric>
#define debug() puts("++++")
#define gcd(a,b) __gcd(a,b)
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define fi first
#define se second
#define pb push_back
#define sqr(x) ((x)*(x))
#define ms(a,b) memset(a,b,sizeof(a))
#define sz size()
#define be begin()
#define pu push_up
#define pd push_down
#define cl clear()
#define lowbit(x) -x&x
#define all 1,n,1
#define mod(x) ((x)%M)
#define pi acos(-1.0)
#define rep(i,x,n) for(int i=(x); i<(n); i++)
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> P;
const int INF = 1<<30;
const int maxn = 5e5+10;
const double eps = 1e-8;
const int dx[] = {-1,1,0,0,1,1,-1,-1};
const int dy[] = {0,0,1,-1,1,-1,1,-1};
int dir[2]={-1,1};
const int mon[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
const int monn[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int s,t,n,m;
inline int read()
{
    int x=0;
    char c=getchar();
    while(c>'9'||c<'0')c=getchar();
    while(c>='0'&&c<='9')x=x*10+c-'0',c=getchar();
    return x;
}
int head[maxn],tot=1;
void init()
{
    ms(head,-1);
    tot=1;
}
struct Pre
{
    int v,edge;//该点的前一个点(从起点过来) 与该点相连的边(靠近起点的)
}pre[maxn];
struct node
{
    int v,w,nxt;
}e[maxn];
void add(int u,int v,int w)
{
    e[++tot].v=v;
    e[tot].w=w;
    e[tot].nxt=head[u];
    head[u]=tot;
}
int inque[maxn];
inline bool bfs()
{
    queue<int> q;
    ms(inque,0);ms(pre,-1);
    inque[s]=1; q.push(s);
    while(!q.empty())
    {
        int u=q.front(); q.pop();
        for(int i=head[u]; i!=-1; i=e[i].nxt)
        {
            int v=e[i].v;
            if(!inque[v]&&e[i].w)
            {
                pre[v].v=u;
                pre[v].edge=i;
                if(v==t) return 1;
                inque[v]=1;
                q.push(v);
            }
        }
    }
    return 0;
}
int ek()
{
    int ans=0;
    while(bfs())
    {
        int mi=INF;
        for(int i=t; i!=s; i=pre[i].v)//每次只能增加增广路上最小的边的权值
        {
            mi = min(mi,e[pre[i].edge].w);
        }
        for(int i=t; i!=s; i=pre[i].v)
        {
            e[ pre[i].edge ].w -= mi;
            e[ pre[i].edge^1 ].w += mi;
        }
        ans += mi;
    }
    return ans;
}
int main()
{
    init();
    n=read(), m=read(), s=read(), t=read();
    int u,v,w;
    for(int i=1;i<=m;i++)
        u=read(),v=read(),w=read(),add(u,v,w),add(v,u,0);
    printf("%d
",ek());
}
/*
4 5 4 3
4 2 30
4 3 20
2 3 20
2 1 30
1 3 40
【题意】

【类型】

【分析】

【时间复杂度&&优化】

【trick】

【数据】

*/

3.HDU 3549 Flow Problem

#include<cstdio>
#include<string>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<cstring>
#include<set>
#include<queue>
#include<algorithm>
#include<vector>
#include<map>
#include<cctype>
#include<stack>
#include<sstream>
#include<list>
#include<assert.h>
#include<bitset>
#include<numeric>
#define debug() puts("++++")
#define gcd(a,b) __gcd(a,b)
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define fi first
#define se second
#define pb push_back
#define sqr(x) ((x)*(x))
#define ms(a,b) memset(a,b,sizeof(a))
#define sz size()
#define be begin()
#define pu push_up
#define pd push_down
#define cl clear()
#define lowbit(x) -x&x
#define all 1,n,1
#define mod(x) ((x)%M)
#define pi acos(-1.0)
#define rep(i,x,n) for(int i=(x); i<(n); i++)
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> P;
const int INF = 1<<30;
const int maxn = 2e3+3;
const double eps = 1e-8;
const int dx[] = {-1,1,0,0,1,1,-1,-1};
const int dy[] = {0,0,1,-1,1,-1,1,-1};
int dir[2]={-1,1};
const int mon[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
const int monn[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int s,t,n,m;
inline int read()
{
    int x=0;
    char c=getchar();
    while(c>'9'||c<'0')c=getchar();
    while(c>='0'&&c<='9')x=x*10+c-'0',c=getchar();
    return x;
}
int head[maxn],tot=1;
void init()
{
    ms(head,-1);
    tot=1;
}
struct Pre
{
    int v,edge;//该点的前一个点(从起点过来) 与该点相连的边(靠近起点的)
}pre[maxn];
struct node
{
    int v,w,nxt;
}e[maxn];
void add(int u,int v,int w)
{
    e[++tot].v=v;
    e[tot].w=w;
    e[tot].nxt=head[u];
    head[u]=tot;
}
int vis[maxn];
inline bool bfs()
{
    queue<int> q;
    ms(vis,0);ms(pre,-1);
    vis[s]=1; q.push(s);
    while(!q.empty())
    {
        int u=q.front(); q.pop();
        if(u==t) return 1;
        for(int i=head[u]; i!=-1; i=e[i].nxt)
        {
            int v=e[i].v;
            if(!vis[v]&&e[i].w)
            {
                pre[v].v=u;
                pre[v].edge=i;
                vis[v]=1;
                q.push(v);
            }
        }
    }
    return 0;
}
int ek()
{
    int ans=0;
    while(bfs())
    {
        int mi=INF;
        for(int i=t; i!=s; i=pre[i].v)//每次只能增加增广路上最小的边的权值
        {
            mi = min(mi,e[pre[i].edge].w);
        }
        for(int i=t; i!=s; i=pre[i].v)
        {
            e[ pre[i].edge ].w -= mi;
            e[ pre[i].edge^1 ].w += mi;
        }
        ans += mi;
    }
    return ans;
}
int main()
{
    int T,ca=1;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&m);
        init();
        s=1,t=n;
        int u,v,w;
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d%d",&u,&v,&w);
            add(u,v,w);
            add(v,u,0);
        }
        printf("Case %d: %d
",ca++,ek());
    }
}
/*
【题意】

【类型】最大流EK算法模板

【分析】

【时间复杂度&&优化】O(nm^2)(n为点数,m为边数)

【trick】

【数据】

*/
原文地址:https://www.cnblogs.com/Roni-i/p/9523110.html