Description:

Network flow is a well-known difficult problem for ACMers. Given a graph, your task is to find out the maximum flow for the weighted directed graph.

Input:

The first line of input contains an integer T, denoting the number of test cases.
For each test case, the first line contains two integers N and M, denoting the number of vertexes and edges in the graph. (2 <= N <= 15, 0 <= M <= 1000)
Next M lines, each line contains three integers X, Y and C, there is an edge from X to Y and the capacity of it is C. (1 <= X, Y <= N, 1 <= C <= 1000)

Output:

For each test cases, you should output the maximum flow from source 1 to sink N.

Sample Input:

2
3 2
1 2 1
2 3 1
3 3
1 2 1
2 3 1
1 3 1

Sample Output:

Case 1: 1
Case 2: 2

题目链接

裸网络流最大流模板题。
网络流基础知识及最大流求解思路:数据结构与算法分析 - 网络流入门(Network Flow)
最大流求解Ford-Fulkerson算法详解:7. 网络流算法–Ford-Fulkerson方法及其多种实现

AC代码:

// Ford-Fulkerson算法
#include <bits/stdc++.h>
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
#define pb push_back
#define mp make_pair
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> P;
const int INF = 0x3f3f3f3f;
const int maxn = 20;
const int mod = 1e9+7;
const double eps = 1e-8;
const double pi = asin(1.0)*2;
const double e = 2.718281828459;
void fre() {
    freopen("in.txt", "r", stdin);
    //freopen("out.txt", "w", stdout);
}

int t;
int n, m;
int x, y, c;
// 起点、终点
int st, en;
// 增广路径流量
int flow;
// 最大流
int ans;
// 顶点标记数组
bool vis[maxn];
// 残留网
int maze[maxn][maxn];

// DFS寻找增广路径
int dfs(int u, int FindFlow) {
    // 若找到汇点返回此增广路径中
    if (u == en) {
        return FindFlow;
    }
    // 若访问过此顶点则返回
    if (vis[u]) {
        return 0;
    }
    // 标记此顶点为已访问顶点
    vis[u] = 1;
    // 枚举寻找下一个顶点
    for (int i = 1; i <= n; ++i) {
        // 跳过两顶点之间容量为0的顶点
        if (maze[u][i]) {
            // 从i点寻找路径,并返回路径流量
            int LastLineFlow = dfs(i, FindFlow < maze[u][i] ? FindFlow : maze[u][i]);
            // 跳过路径流量为0的点
            if (LastLineFlow == 0) {
                continue;
            }
            // 找到增广路径后更新残留网
            maze[u][i] -= LastLineFlow;
            maze[i][u] += LastLineFlow;
            // 返回此增广路径流量
            return LastLineFlow;
        }
    }
    // 若未找到增广路径则返回0
    return 0;
}

int main(){
    //fre();
    scanf("%d", &t);
    for (int Case = 1; Case <= t; ++Case) {
        mem(vis, 0);
        mem(maze, 0);
        scanf("%d%d", &n, &m);
        st = 1, en = n;
        while (m--) {
            scanf("%d%d%d", &x, &y, &c);
            // 这道题有重边所以写为+=,=会WA
            maze[x][y] += c;
        }
        ans = 0;
        // 不断寻找增广路径
        while (flow = dfs(st, INF)) {
            // 增加流量
            ans += flow;
            mem(vis, 0);
        }
        printf("Case %d: %d\n", Case, ans);
    }
    return 0;
}

AC代码:

// Dinic算法
#include <bits/stdc++.h>
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
#define pb push_back
#define mp make_pair
#define lowbit(x) (x&(-x))
#define XDebug(x) cout<<#x<<"="<<x<<endl;
#define ArrayDebug(x,i) cout<<#x<<"["<<i<<"]="<<x[i]<<endl;
#define print(x) out(x);putchar('\n')
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> PII;
typedef pair<double,double> PDD;
typedef pair<ll,ll> PLL;
const int INF = 0x3f3f3f3f;
const int maxn = 20;
const int mod = 1e9 + 7;
const double eps = 1e-8;
const double pi = asin(1.0) * 2;
const double e = 2.718281828459;
template <class T>
inline bool read(T &ret) {
    char c;
    int sgn;
    if (c = getchar(), c == EOF) {
        return false;
    }
    while (c != '-' && (c < '0' || c > '9')) {
        c = getchar();
    }
    sgn = (c == '-') ? -1 : 1;
    ret = (c == '-') ? 0 : (c - '0');
    while (c = getchar(), c >= '0' && c <= '9') {
        ret = ret * 10 + (c - '0');
    }
    ret *= sgn;
    return true;
}
template <class T>
inline void out(T x) {
    if (x < 0) {
        putchar('-');
        x = -x;
    }
    if (x > 9) {
        out(x / 10);
    }
    putchar(x % 10 + '0');
}

int T;
// N:顶点数,E:边数
int N, E;
int X, Y, C;
// 分层数组
int Depth[maxn];
// 邻接矩阵
int Adj[maxn][maxn];

// Bfs搜索分层图,Start:起点,End:终点
bool Bfs(int Start, int End) {
    std::queue<int> Que;
    memset(Depth, -1, sizeof(Depth));
    Depth[Start] = 0;
    Que.push(Start);
    while (!Que.empty()) {
        int Vertex = Que.front();
        Que.pop();
        for (int i = 1; i <= N; ++i) {
            if (Depth[i] == -1 && Adj[Vertex][i]) {
                // 分层编号
                Depth[i] = Depth[Vertex] + 1;
                Que.push(i);
            }
        }
    }
    return Depth[End] > 0;
}

// Dfs搜索增广路径,Vertex:当前搜索顶点,End:终点,NowFlow:当前最大流量
int Dfs(int Vertex, int End, int NowFlow) {
    // 搜索到终点结束
    if (Vertex == End) {
        return NowFlow;
    }
    int FindFlow = 0;
    // 枚举顶点
    for (int i = 1; i <= N; ++i) {
        if (Adj[Vertex][i] && Depth[i] == Depth[Vertex] + 1) {
            FindFlow = Dfs(i, End, std::min(NowFlow, Adj[Vertex][i]));
            if (FindFlow) {
                // 找到增广路径后更新邻接矩阵残留网
                Adj[Vertex][i] -= FindFlow;
                Adj[i][Vertex] += FindFlow;
                // 返回搜索结果
                return FindFlow;
            }
        }
    }
    // 炸点优化
    if (!FindFlow) {
        Depth[Vertex] = -2;
    }
    // 未找到增广路径
    return false;
}

// Dinic算法,Start:起点,End:终点
int Dinic(int Start, int End) {
    // MaxFlow:最大流
    int MaxFlow = 0;
    // 分层搜索增广路径直至终点无法分层
    while (Bfs(Start, End)) {
        MaxFlow += Dfs(Start, End, INF);
    }
    // 返回结果
    return MaxFlow;
}

int main(int argc, char *argv[]) {
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
#endif
    read(T);
    for (int Case = 1; Case <= T; ++Case) {
        mem(Adj, 0);
        read(N); read(E);
        for (int i = 1; i <= E; ++i) {
            read(X); read(Y); read(C);
            Adj[X][Y] += C;
        }
        printf("Case %d: %d\n", Case, Dinic(1, N));
    }
#ifndef ONLINE_JUDGE
    fclose(stdin);
    fclose(stdout);
    system("gedit out.txt");
#endif
    return 0;
}