最大流入门 hdu 3549 ford-fulkerson模板题

详细可以参考挑战。本文只是自己整理下思路。
http://acm.hdu.edu.cn/showproblem.php?pid=3549
题意:求出最大流。
最大流问题:
给一个流网络,每条边有一个容量c(e),实际的传输量f(e)。满足 0<=f(e)<=c(e)
求出从源点s 到 汇点 t 能最大能传输多少。
三个基本概念:残余网络,增广路,割。
残余网络:
由 f(e) < c(e)的e 和满足 f(e) > 0 的 e 对应的反向边rev(e) 所做成的图被称为残余网络。
如果f(u, v) > 0,则在残留网中包含一条容量为f(u, v)的边(v, u);
如果f(u, v) < c(u, v),则在残留网中包含一条容量为c(u, v) - f(u, v)的边(u, v)。
增广路:
一条在残余网络上的s-t 路径被称为增广路。
割:
对于顶点集合S 属于 顶点全集V, 从S出发指向S外部的那些边的集合,称为割(S, V/S)。这些边的容量和被称为割的容量。如果将网络中的s-t割所包含的边都删去,就不存在s到t 的路径了。
又有了最小割的问题:保证不存在一条 s到t 的路径,删去的边的总容量最小是多少?

最大流Ford-Fulkerson 算法:
1)在残余网络中寻找增广路。
2)如果不存在满足的路径,则结束,否则沿着该路劲增加流,接着重复1)。

注释中有详细的解释


#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
#define M 20
#define INF 0x3f3f3f3f
typedef struct
{
    int to,cap,rev; //邻接表存图,cap表示容量,rev 表示反向边的序号
}edge;
vector<edge> G[M];
bool used[M];
int n,m;
//加边
void add_edge(int from,int to,int cap)
{
    G[from].push_back(edge{to,cap,G[to].size()});  //正向边
    G[to].push_back(edge{from,0,G[from].size()-1}); //对应增加反向边
}
//运用dfs求增广路
int dfs(int v,int t,int f)
{
    if(v == t) return f; //到达汇点,返回流量
    used[v] = true; //标记使用
    for(int i = 0;i < G[v].size();i++)
    {
        edge &e = G[v][i]; //记得使用引用
        if(used[e.to] || e.cap <= 0) continue; //若使用过该顶点或容量不够
        int d = dfs(e.to,t,min(e.cap,f)); //保证流量不能超过容量
        if(d > 0)
        {
            e.cap -= d; //此处修改容量,所以之前e要使用引用
            G[e.to][e.rev].cap += d; //反向边增加容量
            return d;
        }
    }
    return 0;
}
int max_flow(int s,int t)
{
    int flow = 0;
    for(;;)
    {
        memset(used,0,sizeof(used));
        int f = dfs(s,t,INF); //寻找增广路
        if(f == 0) return flow; //找不到
        flow += f;
    }
}
int main()
{
    int t;
    scanf("%d",&t);
    for(int cas = 1;cas <= t;cas++)
    {
        scanf("%d %d",&n,&m);
        for(int i = 0;i <= n;i++) G[i].clear();
        for(int i = 0;i < m;i++)
        {
            int a,b,c;
            scanf("%d %d %d",&a,&b,&c);
            add_edge(a,b,c);
        }
        printf("Case %d: %d\n",cas,max_flow(1,n));
    }
    return 0;
}

你可能感兴趣的:(最大流入门 hdu 3549 ford-fulkerson模板题)