最大流、最小割模板

Dinic 模板

 1 struct Edge {
 2     int from, to, cap, flow;
 3 };
 4 struct Dinic {
 5     int n, m, s, t;
 6     vector<Edge>edges;
 7     vector<int>G[MAXN];
 8     bool vis[MAXN];
 9     int d[MAXN];
10     int cur[MAXN];
11     void init(int n) {
12         for (int i = 0; i < MAXN; i++) G[i].clear();
13         edges.clear();memset(d,0,sizeof(d));
14     }
15     void AddEdge(int from, int to, int cap) {
16         edges.push_back({ from, to, cap, 0 });
17         edges.push_back({ to, from, 0, 0 });
18         m = edges.size();
19         G[from].push_back(m - 2);
20         G[to].push_back(m - 1);
21     }
22     bool BFS() {
23         int x, i;
24         memset(vis, 0, sizeof(vis));
25         queue<int>Q;
26         Q.push(s);
27         d[s] = 0;
28         vis[s] = 1;
29         while (!Q.empty()) {
30             x = Q.front(), Q.pop();
31             for (i = 0; i < G[x].size(); i++) {
32                 Edge & e = edges[G[x][i]];
33                 if (!vis[e.to] && e.cap > e.flow) {
34                     vis[e.to] = 1;
35                     d[e.to] = d[x] + 1;
36                     Q.push(e.to);
37                 }
38             }
39         }
40         return vis[t];
41     }
42     int DFS(int x, int a) {
43         if (x == t || a == 0)
44             return a;
45         int flow = 0, f;
46         for (int &i = cur[x]; i < G[x].size(); i++) {
47             Edge & e = edges[G[x][i]];
48             if (d[x] + 1 == d[e.to] && (f = DFS(e.to, min(a, e.cap - e.flow))) > 0) {
49                 e.flow += f;
50                 edges[G[x][i] ^ 1].flow -= f;
51                 flow += f;
52                 a -= f;
53                 if (a == 0)
54                     break;
55             }
56         }
57         return flow;
58     }
59     int Maxflow(int s, int t) {
60         this->s = s, this->t = t;
61         int flow = 0;
62         while (BFS()) {
63             memset(cur, 0, sizeof(cur));
64             flow += DFS(s, INF);
65         }
66         return flow;
67     }
68 };

 


 

Edmonds Karp模板

 1 const int maxn=;
 2 const int inf=0x3f3f3f3f;
 3 struct Edge
 4 {
 5     int from,to,cap,flow;
 6     Edge(int u,int v,int c,int f): from(u),to(v),cap(c),flow(f) {}
 7 };
 8 
 9 struct EdmondsKarp
10 {
11     int n,m;
12     vector<Edge> edges;
13     vector<int> G[maxn];
14     int a[maxn];
15     int p[maxn];
16 
17     void init(int n)
18     {
19       for(int i=0;i<n;i++) G[i].clear();
20       edges.clear();
21     }
22 
23     void AddEdge(int from,int to,int cap)
24     {
25        edges.push_back(Edge(from,to,cap,0));
26        edges.push_back(Edge(to,from,0,0));
27        m=edges.size();
28        G[from].push_back(m-2);
29        G[to].push_back(m-1);
30     }
31 
32    int Maxflow(int s,int t)
33    {
34      int flow=0;
35      while(1)
36      {
37         memset(a,0,sizeof(a));
38         queue<int> Q;
39         Q.push(s);
40         a[s]=inf;
41         while(!Q.empty())
42         {
43             int x=Q.front();Q.pop();
44             for(int i=0;i<G[x].size();i++)
45             {
46                 Edge& e=edges[G[x][i]];
47                 if(!a[e.to]&&e.cap>e.flow)
48                 {
49                     p[e.to]=G[x][i];
50                     a[e.to]=min(a[x],e.cap-e.flow);
51                     Q.push(e.to);
52                 }
53             }
54             if(a[t]) break;
55         }
56         if(!a[t]) break;
57         for(int u=t;u!=s;u=edges[p[u]].from)
58         {
59             edges[p[u]].flow+=a[t];
60             edges[p[u]^1].flow-=a[t];
61         }
62         flow+=a[t];
63     }
64     return flow;    
65    }
66 };

对于最小割来说,在算法结束后,令已经标号的结点(a[u]>0的结点)集合为S,其他集合为T=V-S,则(S,T)是图 s-t 的最小割


 

ISAP,附带Mincut方案

  1 #include<bits/stdc++.h>
  2 #define REP(i, a, b) for(int i = (a); i < (b); i++)
  3 #define MEM(a,x) memset(a,x,sizeof(a)) 
  4 #define INF 0x3f3f3f3f 
  5 #define MAXN 100000+10
  6 using namespace std;
  7 
  8 struct Edge
  9 {
 10     int from, to, cap, flow;
 11     Edge(int u, int v, int c, int f) :from(u), to(v), cap(c), flow(f) {}
 12 };
 13 
 14 struct ISAP
 15 {
 16     int n, m, s, t;
 17     vector<Edge>edges;
 18     vector<int>G[MAXN];
 19     bool vis[MAXN];
 20     int d[MAXN], cur[MAXN];
 21     int p[MAXN], num[MAXN];//比Dinic算法多了这两个数组,p数组标记父亲结点,num数组标记距离d[i]存在几个
 22     void addedge(int from, int to, int cap)
 23     {
 24         edges.push_back(Edge(from, to, cap, 0));
 25         edges.push_back(Edge(to, from, 0, 0));
 26         int m = edges.size();
 27         G[from].push_back(m - 2);
 28         G[to].push_back(m - 1);
 29     }
 30 
 31     void init(int n) {
 32         this->n = n;
 33         for (int i = 0; i < n; i++) {
 34             G[i].clear();
 35         }
 36         edges.clear();
 37     }
 38 
 39     int Augumemt()
 40     {
 41         int x = t, a = INF;
 42         while (x != s)//找最小的残量值
 43         {
 44             Edge&e = edges[p[x]];
 45             a = min(a, e.cap - e.flow);
 46             x = edges[p[x]].from;
 47         }
 48         x = t;
 49         while (x != s)//增广
 50         {
 51             edges[p[x]].flow += a;
 52             edges[p[x] ^ 1].flow -= a;//更新反向边。
 53             x = edges[p[x]].from;
 54         }
 55         return a;
 56     }
 57     void BFS()//逆向进行bfs
 58     {
 59         memset(vis, 0, sizeof(vis));
 60         queue<int>q;
 61         q.push(t);
 62         d[t] = 0;
 63         vis[t] = 1;
 64         while (!q.empty())
 65         {
 66             int x = q.front(); q.pop();
 67             int len = G[x].size();
 68             for (int i = 0; i < len; i++)
 69             {
 70                 Edge&e = edges[G[x][i]];
 71                 if (!vis[e.from] && e.cap > e.flow)
 72                 {
 73                     vis[e.from] = 1;
 74                     d[e.from] = d[x] + 1;
 75                     q.push(e.from);
 76                 }
 77             }
 78         }
 79     }
 80 
 81     int Maxflow(int s, int t)//根据情况前进或者后退,走到汇点时增广
 82     {
 83         this->s = s;
 84         this->t = t;
 85         int flow = 0;
 86         BFS();
 87         memset(num, 0, sizeof(num));
 88         for (int i = 0; i < n; i++)
 89             num[d[i]]++;
 90         int x = s;
 91         memset(cur, 0, sizeof(cur));
 92         while (d[s] < n)
 93         {
 94             if (x == t)//走到了汇点,进行增广
 95             {
 96                 flow += Augumemt();
 97                 x = s;//增广后回到源点
 98             }
 99             int ok = 0;
100             for (int i = cur[x]; i < G[x].size(); i++)
101             {
102                 Edge&e = edges[G[x][i]];
103                 if (e.cap > e.flow&&d[x] == d[e.to] + 1)
104                 {
105                     ok = 1;
106                     p[e.to] = G[x][i];//记录来的时候走的边,即父边
107                     cur[x] = i;
108                     x = e.to;//前进
109                     break;
110                 }
111             }
112             if (!ok)//走不动了,撤退
113             {
114                 int m = n - 1;//如果没有弧,那么m+1就是n,即d[i]=n
115                 for (int i = 0; i < G[x].size(); i++)
116                 {
117                     Edge&e = edges[G[x][i]];
118                     if (e.cap > e.flow)
119                         m = min(m, d[e.to]);
120                 }
121                 if (--num[d[x]] == 0)break;//如果走不动了,且这个距离值原来只有一个,那么s-t不连通,这就是所谓的“gap优化”
122                 num[d[x] = m + 1]++;
123                 cur[x] = 0;
124                 if (x != s)
125                     x = edges[p[x]].from;//退一步,沿着父边返回
126             }
127         }
128         return flow;
129     }
130     vector<int>Mincut() {
131         BFS();
132         vector<int>ans;
133         for (int i = 0; i < edges.size(); i++) {
134             Edge& e = edges[i];
135             if (!vis[e.from] && vis[e.to] && e.cap > 0)
136                 ans.push_back(i);
137         }
138         return ans;
139     }
140 };

 

转载于:https://www.cnblogs.com/romaLzhih/p/9567387.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值