一.模板

 

1.最大流

EK算法:


网络流总结_unix网络流总结_最小割_02


1 #include <iostream>             //EK算法
2 #include <queue>
3 #include<string.h>
4 using namespace std;
5 #define arraysize 201
6 int maxData = 0x7fffffff;
7 int capacity[arraysize][arraysize]; //记录残留网络的容量
8 int flow[arraysize]; //标记从源点到当前节点实际还剩多少流量可用
9 int pre[arraysize]; //标记在这条路径上当前节点的前驱,同时标记该节点是否在队列中
10 int n,m;
11
12 queue<int> myqueue;
13 int BFS(int src,int des)
14 {
15 int i,j;
16 while(!myqueue.empty()) //队列清空
17 myqueue.pop();
18 for(i=1;i<m+1;++i)
19 {
20 pre[i]=-1;
21 }
22 pre[src]=0;
23 flow[src]= maxData;
24 myqueue.push(src);
25 while(!myqueue.empty())
26 {
27 int index = myqueue.front();
28 myqueue.pop();
29 if(index == des) //找到了增广路径
30 break;
31 for(i=1;i<m+1;++i)
32 {
33 if(i!=src && capacity[index][i]>0 && pre[i]==-1)
34 {
35 pre[i] = index; //记录前驱
36 flow[i] = min(capacity[index][i],flow[index]); //关键:迭代的找到增量
37 myqueue.push(i);
38 }
39 }
40 }
41 if(pre[des]==-1) //残留图中不再存在增广路径
42 return -1;
43 else
44 return flow[des];
45 }
46
47 int maxFlow(int src,int des)
48 {
49 int increasement= 0;
50 int sumflow = 0;
51 while((increasement=BFS(src,des))!=-1)
52 {
53 int k = des; //利用前驱寻找路径
54 while(k!=src)
55 {
56 int last = pre[k];
57 capacity[last][k] -= increasement; //改变正向边的容量
58 capacity[k][last] += increasement; //改变反向边的容量
59 k = last;
60 }
61 sumflow += increasement;
62 }
63 return sumflow;
64 }
65
66 int main()
67 {
68 int i,j;
69 int start,end,ci;
70 while(cin>>n>>m)
71 {
72 memset(capacity,0,sizeof(capacity));
73 memset(flow,0,sizeof(flow));
74 for(i=0;i<n;++i)
75 {
76 cin>>start>>end>>ci;
77 if(start == end) //考虑起点终点相同的情况
78 continue;
79 capacity[start][end] +=ci; //此处注意可能出现多条同一起点终点的情况
80 }
81 cout<<maxFlow(1,m)<<endl;
82 }
83 return 0;
84 }

View Code

DINIC算法:


网络流总结_unix网络流总结_最小割_02


1 #include <cstdio>           ///dinic算法
2 #include <cstring>
3 #include <iostream>
4 #include <queue>
5 #include <vector>
6
7 using namespace std;
8
9 const int Maxn = 10000 + 10;
10 const int INF = 0x6fffffff >> 2;
11
12 struct edge
13 {
14 int from , to , cap , flow;
15 };
16
17 struct Dinic{
18 int n,m,s,t;
19 vector<edge> edges;
20 vector<int> f[Maxn];
21 bool vis[Maxn];
22 int d[Maxn];
23 int cur[Maxn];
24
25 void AddEdge(int from,int to,int cap)
26 {
27 edges.push_back((edge){from,to,cap,0});
28 edges.push_back((edge){to,from,0,0});
29 m = edges.size();
30 f[from].push_back(m-2);
31 f[to].push_back(m-1);
32 }
33
34 bool BFS()
35 {
36 memset(vis,0,sizeof(vis));
37 queue<int> q;
38 q.push(s);
39 d[s] = 0;
40 vis[s] = 1;
41 while(!q.empty())
42 {
43 int x = q.front(); q.pop();
44 for(int i=0;i<f[x].size();i++)
45 {
46 edge &e = edges[f[x][i]];
47 if(!vis[e.to] && e.flow < e.cap) //只考虑残留网络中的弧
48 {
49 vis[e.to] = 1;
50 d[e.to] = d[x] + 1;//层次图
51 q.push(e.to);
52 }
53 }
54 }
55 return vis[t];//能否到汇点,不能就结束
56 }
57 int DFS(int x,int a)//x为当前节点,a为当前最小残量
58 {
59 if(x == t || a == 0) return a;
60 int flow = 0 , r;
61
62 for(int& i = cur[x];i < f[x].size();i++)
63 {
64 edge& e = edges[f[x][i]];
65 if(d[x] + 1 == d[e.to] && (r = DFS(e.to , min(a,e.cap - e.flow) ) ) > 0 )
66 {
67 e.flow += r;
68 edges[f[x][i] ^ 1].flow -= r;
69 flow += r;//累加流量
70 a -= r;
71 if(a == 0) break;
72 }
73 }
74 return flow;
75 }
76 int MaxFlow(int s,int t)
77 {
78 this->s = s; this->t = t;
79 int flow = 0;
80 while(BFS())
81 {
82
83 memset(cur,0,sizeof(cur));
84 flow += DFS(s,INF);
85 }
86 return flow;
87 }
88 }G;
89
90 int main()
91 {
92 int x,y,z;
93 int s,t;
94 scanf("%d",&G.n);
95 while(1)
96 {
97 scanf("%d%d%d",&x,&y,&z);
98 if(!(x|y|z)) break;
99 G.AddEdge(x,y,z);
100 }
101 scanf("%d%d",&s,&t);
102 printf("%d\n",G.MaxFlow(s,t));
103 return 0;
104 }

View Code

sap领接矩阵:


网络流总结_unix网络流总结_最小割_02


1 int maze[MAXN][MAXN];
2 int gap[MAXN], dis[MAXN], pre[MAXN], cur[MAXN];
3 int flow[MAXN][MAXN];
4
5 int sap(int start, int end, int nodenum)
6 {
7 memset(cur, 0, sizeof(cur));
8 memset(dis, 0, sizeof(dis));
9 memset(gap, 0, sizeof(gap));
10 memset(flow, 0, sizeof(flow));
11 int u = pre[start] = start, maxflow = 0, aug = INF;
12 gap[0] = nodenum;
13
14 while(dis[start]<nodenum)
15 {
16 loop:
17 for(int v = cur[u]; v<nodenum; v++)
18 if(maze[u][v]-flow[u][v]>0 && dis[u] == dis[v]+1)
19 {
20 aug = min(aug, maze[u][v]-flow[u][v]);
21 pre[v] = u;
22 u = cur[u] = v;
23 if(v==end)
24 {
25 maxflow += aug;
26 for(u = pre[u]; v!=start; v = u, u = pre[u])
27 {
28 flow[u][v] += aug;
29 flow[v][u] -= aug;
30 }
31 aug = INF;
32 }
33 goto loop;
34 }
35
36 int mindis = nodenum-1;
37 for(int v = 0; v<nodenum; v++)
38 if(maze[u][v]-flow[u][v]>0 && mindis>dis[v])
39 {
40 cur[u] = v;
41 mindis = dis[v];
42 }
43 if((--gap[dis[u]])==0) break;
44 gap[dis[u]=mindis+1]++;
45 u = pre[u];
46 }
47 return maxflow;
48 }

View Code

sap领接表:


网络流总结_unix网络流总结_最小割_02


1 struct Edge
2 {
3 int to, next, cap, flow;
4 }edge[MAXN*MAXN];
5 int tot, head[MAXN];
6
7 int uN, vN, maze[MAXN][MAXN];
8 int gap[MAXN], dep[MAXN], pre[MAXN], cur[MAXN];
9
10 void add(int u, int v, int w)
11 {
12 edge[tot].to = v; edge[tot].cap = w; edge[tot].flow = 0;
13 edge[tot].next = head[u]; head[u] = tot++;
14 edge[tot].to = u; edge[tot].cap = 0; edge[tot].flow = 0;
15 edge[tot].next = head[v]; head[v] = tot++;
16 }
17
18 int sap(int start, int end, int nodenum)
19 {
20 memset(dep, 0, sizeof(dep));
21 memset(gap, 0, sizeof(gap));
22 memcpy(cur, head, sizeof(head));
23 int u = pre[start] = start, maxflow = 0,aug = INF;
24 gap[0] = nodenum;
25 while(dep[start]<nodenum)
26 {
27 loop:
28 for(int i = cur[u]; i!=-1; i = edge[i].next)
29 {
30 int v = edge[i].to;
31 if(edge[i].cap-edge[i].flow && dep[u]==dep[v]+1)
32 {
33 aug = min(aug, edge[i].cap-edge[i].flow);
34 pre[v] = u;
35 cur[u] = i;
36 u = v;
37 if(v==end)
38 {
39 maxflow += aug;
40 for(u = pre[u]; v!=start; v = u,u = pre[u])
41 {
42 edge[cur[u]].flow += aug;
43 edge[cur[u]^1].flow -= aug;
44 }
45 aug = INF;
46 }
47 goto loop;
48 }
49 }
50 int mindis = nodenum - 1;
51 for(int i = head[u]; i!=-1; i = edge[i].next)
52 {
53 int v=edge[i].to;
54 if(edge[i].cap-edge[i].flow && mindis>dep[v])
55 {
56 cur[u] = i;
57 mindis = dep[v];
58 }
59 }
60 if((--gap[dep[u]])==0)break;
61 gap[dep[u]=mindis+1]++;
62 u = pre[u];
63 }
64 return maxflow;
65 }

View Code

isap算法:


网络流总结_unix网络流总结_最小割_02


1 struct Edge
2 {
3 int to, next, cap, flow;
4 }edge[MAXN<<2];
5 int tot, head[MAXN];
6
7 int gap[MAXN], dep[MAXN], cur[MAXN];
8
9 void init()
10 {
11 tot = 0;
12 memset(head, -1, sizeof(head));
13 }
14
15 void add(int u, int v, int w)
16 {
17 edge[tot].to = v; edge[tot].cap = w; edge[tot].flow = 0;
18 edge[tot].next = head[u]; head[u] = tot++;
19 edge[tot].to = u; edge[tot].cap = 0; edge[tot].flow = 0;
20 edge[tot].next = head[v]; head[v] = tot++;
21 }
22
23 int Q[MAXN];
24 void BFS(int start, int end)
25 {
26 memset(dep,-1,sizeof(dep));
27 memset(gap,0,sizeof(gap));
28 dep[end] = 0;
29 gap[0] = 1;
30 int front = 0, rear = 0;
31 Q[rear++] = end;
32 while(front!=rear)
33 {
34 int u = Q[front++];
35 for(int i = head[u]; i!=-1; i=edge[i].next)
36 {
37 int v = edge[i].to;
38 if(dep[v]!=-1) continue;
39 Q[rear++] = v;
40 dep[v] = dep[u]+1;
41 gap[dep[v]]++;
42 }
43 }
44 }
45
46 int S[MAXN];
47 int sap(int start, int end, int N)
48 {
49 BFS(start, end);
50 memcpy(cur,head,sizeof(head));
51 int top = 0;
52 int u = start;
53 int ans = 0;
54 while(dep[start]<N)
55 {
56 if(u==end)
57 {
58 int Min = INF;
59 int inser;
60 for(int i = 0; i<top; i++)
61 if(Min>edge[S[i]].cap-edge[S[i]].flow)
62 {
63 Min = edge[S[i]].cap-edge[S[i]].flow;
64 inser = i;
65 }
66 for(int i = 0; i<top; i++)
67 {
68 edge[S[i]].flow += Min;
69 edge[S[i]^1].flow -= Min;
70 }
71 ans += Min;
72 top = inser;
73 u = edge[S[top]^1].to;
74 continue;
75 }
76
77 bool flag = false;
78 int v;
79 for(int i = cur[u]; i!=-1; i = edge[i].next)
80 {
81 v = edge[i].to;
82 if(edge[i].cap-edge[i].flow && dep[v]+1==dep[u])
83 {
84 flag = true;
85 cur[u] = i;
86 break;
87 }
88 }
89
90 if(flag)
91 {
92 S[top++] = cur[u];
93 u = v;
94 continue;
95 }
96
97 int Min = N;
98 for(int i = head[u]; i!=-1; i = edge[i].next)
99 if(edge[i].cap-edge[i].flow && dep[edge[i].to]<Min)
100 {
101 Min = dep[edge[i].to];
102 cur[u] = i;
103 }
104 if((--gap[dep[u]])==0) break;
105 gap[dep[u]=Min+1]++;
106 if(u!=start) u = edge[S[--top]^1].to;
107 }
108 return ans;
109 }

View Code

 

2.最小割(没有源汇点):


网络流总结_unix网络流总结_最小割_02


1 int mp[MAXN][MAXN];
2 bool combine[MAXN];
3 int n, m;
4
5 bool vis[MAXN];
6 int w[MAXN];
7 int prim(int times, int &s, int &t) //最大生成树?
8 {
9 memset(w,0,sizeof(w));
10 memset(vis,0,sizeof(vis));
11 for(int i = 1; i<=times; i++) //times为实际的顶点个数
12 {
13 int k, maxx = -INF;
14 for(int j = 0; j<n; j++)
15 if(!vis[j] && !combine[j] && w[j]>maxx)
16 maxx = w[k=j];
17
18 vis[k] = 1;
19 s = t; t = k;
20 for(int j = 0; j<n; j++)
21 if(!vis[j] && !combine[j])
22 w[j] += mp[k][j];
23 }
24 return w[t];
25 }
26
27 int mincut()
28 {
29 int ans = INF;
30 memset(combine,0,sizeof(combine));
31 for(int i = n; i>=2; i--) //每一次循环,就减少一个点
32 {
33 int s, t;
34 int tmp = prim(i, s, t);
35 ans = min(ans, tmp);
36 combine[t] = 1;
37 for(int j = 0; j<n; j++) //把t点删掉,与t相连的边并入s
38 {
39 mp[s][j] += mp[t][j];
40 mp[j][s] += mp[j][t];
41 }
42 }
43 return ans;
44 }

View Code

 

3.最小费用流:


网络流总结_unix网络流总结_最小割_02


1 struct Edge
2 {
3 int to, next, cap, flow, cost;
4 }edge[10010<<2];
5 int tot, head[MAXN];
6 int pre[MAXN], dis[MAXN];
7 bool vis[MAXN];
8 int N;
9
10 void init(int n)
11 {
12 N = n;
13 tot = 0;
14 memset(head, -1, sizeof(head));
15 }
16
17 void add(int u, int v, int cap, int cost)
18 {
19 edge[tot].to = v; edge[tot].cap = cap; edge[tot].cost = cost;
20 edge[tot].flow = 0; edge[tot].next = head[u]; head[u] = tot++;
21 edge[tot].to = u; edge[tot].cap = 0; edge[tot].cost = -cost;
22 edge[tot].flow = 0; edge[tot].next = head[v]; head[v] = tot++;
23 }
24
25 bool spfa(int s, int t)
26 {
27 queue<int>q;
28 for(int i = 0; i<=N; i++)
29 {
30 dis[i] = INF;
31 vis[i] = false;
32 pre[i] = -1;
33 }
34
35 dis[s] = 0;
36 vis[s] = true;
37 q.push(s);
38 while(!q.empty())
39 {
40 int u = q.front();
41 q.pop();
42 vis[u] = false;
43 for(int i = head[u]; i!=-1; i = edge[i].next)
44 {
45 int v = edge[i].to;
46 if(edge[i].cap>edge[i].flow && dis[v]>dis[u]+edge[i].cost)
47 {
48 dis[v] = dis[u]+edge[i].cost;
49 pre[v] = i;
50 if(!vis[v])
51 {
52 vis[v] = true;
53 q.push(v);
54 }
55 }
56 }
57 }
58 if(pre[t]==-1) return false;
59 return true;
60 }
61
62 int minCostMaxFlow(int s, int t, int &cost)
63 {
64 int flow = 0;
65 cost = 0;
66 while(spfa(s,t))
67 {
68 int Min = INF;
69 for(int i = pre[t]; i!=-1; i = pre[edge[i^1].to])
70 {
71 if(Min>edge[i].cap-edge[i].flow)
72 Min = edge[i].cap-edge[i].flow;
73 }
74 for(int i = pre[t]; i!=-1; i = pre[edge[i^1].to])
75 {
76 edge[i].flow += Min;
77 edge[i^1].flow -= Min;
78 cost += edge[i].cost*Min;
79 }
80 flow += Min;
81 }
82 return flow;
83 }

View Code