随笔-Dinic

Posted wuyuema

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了随笔-Dinic相关的知识,希望对你有一定的参考价值。

首先是一个很简单的dfs求最大流算法(FF),代码如下

 1 #include <bits/stdc++.h>
 2 #define MAXN 300
 3 #define INF 19930317
 4  
 5 int c[MAXN][MAXN];
 6 int s, t, i, k, u, v, w, n, m;
 7 int flow, Res;
 8 int vis[MAXN];
 9  
10 int dfs(int u, int low) {
11     int i, flow;
12     if (u == t)
13         return low;
14     if (vis[u])
15         return 0;
16     vis[u] = 1;
17     for (i = 1; i <= n; i++)
18         if (c[u][i] && (flow = dfs(i, low < c[u][i] ? low : c[u][i]))) {
19             c[u][i] -= flow;
20             c[i][u] += flow;
21             return flow;
22         }
23     return 0;
24 }
25  
26  
27 int main() {
28     scanf("%d%d", &m, &n);
29     for (i = 1; i <= m; i++) {
30         scanf("%d%d%d", &u, &v, &w);
31         c[u][v] += w;
32     }
33     s = 1;
34     t = n;
35     while (flow = dfs(s, INF)) {
36         Res += flow;
37         memset(vis, 0, sizeof(vis));
38     }
39     printf("%d
", Res);
40 }

 

这是Dinic算法的基础。此外为了方便反向边的查找,将存储图的数据结构更改成如下。

struct Edge {
    int from, to, w;
};
vector<int>tab[maxn];
vector<Edge>edg;

 

相当于是把所有边都按照输入顺序存下来,再分配给各个边。同时,边edg[i]的反向边为edg[i ^ 2]。

 

接下来是Dinic。

 1 struct Edge {
 2     int from, to, cap, w;
 3 };
 4 vector<int>tab[maxn];
 5 vector<Edge>edg;
 6 bool vis[maxn];
 7 int dep[maxn];
 8 int cur[maxn];
 9 void adde(int u, int v, int w) {
10     edg.push_back((edge){u, v, w, 0});
11     edg.push_back((edge){v, u, 0, 0});
12     int M = edg.size();
13     tab[from].push_back(M - 2);
14     tab[to].push_back(M - 1);
15 }        
16 bool bfs() {
17     memset(vis, 0, sizeof(vis));
18     queue<int>q;
19     q.push(s);
20     dep[s] = 0;
21     vis[s] = 1;
22     while (!q.empty()) {
23         int u = q.front(); q.pop();
24         for (int i = 0; i < tab[u].size(); i++) {
25             Edge& e = edg[tab[u][i]];
26             if (!vis[e.to] && e.cap > e.w) {
27                 vis[e.to] = 1;
28                 q.push(e.to);
29                 dep[e.to] = dep[u] + 1;
30             }
31         }
32     }
33     return vis[t];
34 }
35 int dfs(int u, int low) {
36     if (u == t || low == 0) return low;
37     int sum = 0, flow;
38     for (int& i = cur[u]; i < tab[u].size(); i++) {
39         Edge& e = edg[tab[u][i]];
40         if (dep[u] + 1 == dep[e.to] && (flow = dfs(e.to, min(low, e.cap - e.sum))) > 0) {
41             e.sum += flow;
42             edg[tab[u][i] ^ 1].sum -= flow;
43             sum += flow;
44             low -= flow;
45             if (sum == 0) break;
46         }
47     }
48     return sum;
49 }
50 int maxFlow(int s, int t) {
51     int flow = 0;
52     while (bfs()) {
53         memset(cur, 0, sizeof(cur));
54         flow += dfs(s, INF);
55     }
56     return flow;
57 }

我写完了。

#include <bits/stdc++.h>
#define MAXN 300
#define INF 19930317
 
int c[MAXN][MAXN];
int s, t, i, k, u, v, w, n, m;
int flow, Res;
int vis[MAXN];
 
int dfs(int u, int low) {
    int i, flow;
    if (u == t)
        return low;
    if (vis[u])
        return 0;
    vis[u] = 1;
    for (i = 1; i <= n; i++)
        if (c[u][i] && (flow = dfs(i, low < c[u][i] ? low : c[u][i]))) {
            c[u][i] -= flow;
            c[i][u] += flow;
            return flow;
        }
    return 0;
}
 
 
int main() {
    scanf("%d%d", &m, &n);
    for (i = 1; i <= m; i++) {
        scanf("%d%d%d", &u, &v, &w);
        c[u][v] += w;
    }
    s = 1;
    t = n;
    while (flow = dfs(s, INF)) {
        Res += flow;
        memset(vis, 0, sizeof(vis));
    }
    printf("%d ", Res);
}

以上是关于随笔-Dinic的主要内容,如果未能解决你的问题,请参考以下文章

dinic

占棋盘(最大流 dinic)

P3376 (最大流 dinic)

网络最大流算法—Dinic算法及优化

网络流最大流入门(Dinic算法)模板

CH#17C 舞动的夜晚(Dinic+tarjan)