图论——网络流
首先先上一个自己觉的非常ok的博客:大佬的博客
这里我觉的要讲的是这个算法的主要组件:链式前向星,deep数组,前者用来存图,后者用来记录每个点的深度(方便dfs搜索)
来个板子题:洛谷P1343
#include<iostream> #include<string> #include<cstring> #include<queue> #include<cstdio> using namespace std; const int maxn = 300; int n; //网络流的终点是n int cnt; //链式前向星的组件 int deep[maxn]; // 记录点的深度 int head[maxn]; struct node{ int u, v, w, next; }edge[maxn*30]; void add(int u, int v, int w){ edge[cnt].u = u; edge[cnt].v = v; edge[cnt].w = w; edge[cnt].next = head[u]; head[u] = cnt++; } int bfs() { memset(deep, -1, sizeof(deep));//初始化为-1,因为每次因为前面进行了一次dfs,每个点的w值都会发生变化 deep[1] = 0; //起始点1的深度为0 queue<int> q; q.push(1); while(q.size()) { int u = q.front(); q.pop(); for(int i = head[u]; ~i; i = edge[i].next) { int v = edge[i].v; if(deep[v] == -1 && edge[i].w > 0)//如果说这个v点没有被访问,并且他还可以有余量就放到dfs的搜索编号中 { deep[v] = deep[u]+1;//深度+1,继续bfs q.push(v); } } } return deep[n] != -1; //如果deep【n】为-1,很有可能中间的某个路是0,导致不能再继续到达n点,返回0 } int dfs(int u, int all)//当前点是u, 他剩下给他的子树的余量是all { if(u == n) return all; int all1 = all; for(int i = head[u]; ~i; i = edge[i].next) { int v = edge[i].v; if(deep[v] == deep[u] + 1 && edge[i].w > 0)//是下一个深度的点,并且他有余量 { int d = dfs(v, min(all, edge[i].w));//父亲的余量和自己的最大的通过量的最小化 all -= d; //更新残量,为u的下一个连接点做准备 edge[i].w -= d; edge[i^1].w += d; if(all == 0) //如果全部用完了,也没有继续搜索下去的必要了 break; } } return all1 - all;//返回使用的量 } int dinic() { int ans = 0; while(bfs()) { ans += dfs(1, 1e9); } return ans; } void ini() { cnt = 0; for(int i = 0; i < maxn; i++) head[i] = -1; } int main() { int m, x; cin >> n >> m >> x; int u, v, w; ini(); for(int i = 0; i < m; i++) { cin >> u >> v >> w; add(u, v, w); add(v, u, 0); } int ans = dinic(); if(ans == 0) printf("Orz Ni Jinan Saint Cow!\n"); else { if(x%ans) printf("%d %d\n", ans, x/ans+1); else printf("%d %d\n", ans, x/ans); } return 0; }
再来一个POJ练习下:POJ1459Power Network
注意这个题目你会发现其实是多源点,多汇点的,但是其实只要自己在设置一个超级源点,连接多源点,设置一个超级汇点,连接多个汇点就好了
#include<iostream> #include<string> #include<queue> #include<cstring> using namespace std; const int maxn = 200; int sta, end; int cnt; int head[maxn]; int map[maxn][maxn]; struct node{ int u, v, w, next; }edge[maxn*maxn]; void add(int u, int v, int w) { edge[cnt].u = u; edge[cnt].v = v; edge[cnt].w = w; edge[cnt].next = head[u]; map[u][v] = cnt; head[u] = cnt++; } int deep[maxn]; int bfs() { memset(deep, -1, sizeof(deep)); queue<int> q; deep[sta] = 0; q.push(sta); while(q.size()) { int u = q.front(); q.pop(); for(int i = head[u]; ~i; i = edge[i].next) { int v = edge[i].v; if(deep[v] == -1 && edge[i].w > 0) { deep[v] = deep[u] + 1; q.push(v); } } } return deep[end] != -1; } int dfs(int u, int all) { if(u == end) return all; int all1 = all; for(int i = head[u]; ~i; i = edge[i].next) { int v = edge[i].v; if(deep[v] == deep[u] + 1 && edge[i].w > 0) { int d = dfs(v, min(edge[i].w, all)); all -=d; edge[i].w -= d; edge[i^1].w += d; if(all == 0) break; } } return all1 - all; } int dinic() { int ans = 0; while(bfs()) { ans += dfs(sta, 1e9); } return ans; } void ini() { memset(map, 0, sizeof(map)); for(int i = 0; i < maxn; i++) head[i] = -1; cnt = 0; } int main() { int n, np, nc, m; while(cin >> n >> np >> nc >> m) { int u, v, w; ini(); for(int i = 0 ; i < m; i++) { scanf(" (%d,%d)%d", &u, &v, &w); if(map[u][v]) { edge[map[u][v]].w += w; } else if(map[v][u]) { edge[map[v][u]^1].w += w; } else { add(u, v, w); add(v, u, 0); } } sta = n, end = n+1; u = sta; for(int i = 0; i < np; i++) { scanf(" (%d)%d", &v, &w); if(map[u][v]) { edge[map[u][v]].w += w; } else if(map[v][u]) { edge[map[v][u]^1].w += w; } else { add(u, v, w); add(v, u, 0); } } v = end; for(int i = 0; i < nc; i++) { scanf(" (%d)%d", &u, &w); if(map[u][v]) { edge[map[u][v]].w += w; } else if(map[v][u]) { edge[map[v][u]^1].w += w; } else { add(u, v, w); add(v, u, 0); } } printf("%d\n", dinic()); } return 0; }

浙公网安备 33010602011771号