Dinic算法求解最大流问题
题目:luogu 3376
分析:用Dinic算法求解最大流问题,复杂度为$O(mn^{2})$. 核心有两部分:利用BFS构造level graph, 然后用DFS找增广路径。代码如下,难点在于函数DFS(start, flow), 返回从结点start出发到$t$的最大流,并且满足流值不超过flow.
#include<iostream> #include<queue> #include<algorithm> #include<string.h> using namespace std; //n<=200, m<=5000, w<=2^31-1 (int) int utoe[205];//结点u对应的边e的编号 int level[205];//每个结点的level number long long INF = 429496729400; int s, t; long long maxflow; struct { long long cap;//边的容量 int toVer;//边(u,v)对应的v int nex;//边(u,v1)上一条共起点的边(u,v2)的编号 } edge[10005]; bool constructLG()//构造level graph { queue<int>q; memset(level, -1, sizeof(level));//每个结点的level初始化为-1 int e_idx;//边的编号 int top_ele;//队首元素(结点编号) int v_temp; q.push(s); level[s] = 0; while (!q.empty()) { top_ele = q.front(); q.pop(); e_idx=utoe[top_ele]; while (e_idx >= 0) { v_temp = edge[e_idx].toVer; if (edge[e_idx].cap > 0 && level[v_temp] == -1) { q.push(v_temp); level[v_temp] = level[top_ele] + 1; if (v_temp == t) return true; } e_idx = edge[e_idx].nex; } } return false; } long long DFS(int start, long long flow)//flow是为结点start分配的flow value { long long res = 0; long long subflow; if (start == t) return flow; int e_idx=utoe[start]; int v_temp; while (e_idx>=0 && flow>0)//flow如果为零,没必要再搜索下去 { v_temp = edge[e_idx].toVer; if (level[v_temp] == level[start] + 1 && edge[e_idx].cap > 0) { subflow=DFS(v_temp,min(flow,edge[e_idx].cap)); if (subflow == 0)//剪枝 level[v_temp] = -1; edge[e_idx].cap -= subflow; edge[e_idx ^ 1].cap += subflow; res += subflow; flow -= subflow; } e_idx = edge[e_idx].nex; } return res; } void Dinic() { while (constructLG()) maxflow+=DFS(s, INF); } int main() { int n, m; int u, v, c; int id_e; int i; while (scanf("%d%d%d%d", &n, &m, &s, &t) == 4) { id_e = -1; memset(utoe, -1, sizeof(utoe)); for (i = 1; i <= m; i++) { scanf("%d%d%d", &u, &v, &c); edge[++id_e].cap = c; edge[id_e].toVer = v; edge[id_e].nex = utoe[u]; utoe[u] = id_e; edge[++id_e].cap = 0; edge[id_e].toVer = u; edge[id_e].nex = utoe[v]; utoe[v] = id_e; } maxflow = 0; Dinic(); printf("%lld\n", maxflow); } return 0; }