网络流-求解最大流的算法:
Dinic算法
- 通过BFS构建层次网络
- 通过DFS寻找增广路
EK算法
- 通过BFS找到一条到达汇点的路径,记录该路径
- 将该路径的残存流量减去路径上的最小流量
配题:HDU 3549
题意:构建网络,寻找点 1 到 点 N 的最大流。
注意:建图时候偶数边都是正向边,奇数边都是反向边,反之亦然。使用前向星建图,可以很好地提取一条正向边的反向边但是使用vector构建的邻接表,要注意构建的手法,graph 和 edge 的构建技术。
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<queue>
using namespace std;
const int maxN = 20;
const int maxM = 2005;
const int INF = 0x7fffffff;
struct EDGE
{
int u, v;
int flow;
EDGE(){}
EDGE(int u, int v, int flow): u(u), v(v), flow(flow){}
};
int N, M;
vector<EDGE>edge;
vector<int>graph[maxN];
int depth[maxN];
int MIN(const int a, const int b)
{
if (a < b) return a;
return b;
}
void add_edge(int u, int v, int cap)
{
edge.push_back(EDGE(u, v, cap));
edge.push_back(EDGE(v, u, 0));
int cnt = edge.size();
graph[u].push_back(cnt - 2);
graph[v].push_back(cnt - 1);
}
bool dinic_bfs(int source, int sink)
{
queue<int>q;
while (!q.empty()) q.pop();
memset(depth, 0, sizeof(depth));
depth[source] = 1;
q.push(source);
while (!q.empty())
{
int cur_node = q.front();
q.pop();
for (int i = 0; i < graph[cur_node].size(); i++)
{
int id = graph[cur_node][i];
int next_node = edge[id].v;
int flow = edge[id].flow;
if (depth[next_node] == 0 && flow > 0)
{
depth[next_node] = depth[cur_node] + 1;
q.push(next_node);
}
}
}
if (depth[sink])
{
return true;
}
else
{
return false;
}
}
int dinic_dfs(int cur_node, int sink, int min_flow)
{
if (cur_node == sink)
{
return min_flow;
}
for (int i = 0; i < graph[cur_node].size(); i++)
{
int id = graph[cur_node][i];
int next_node = edge[id].v;
int flow = edge[id].flow;
if (depth[next_node] == depth[cur_node] + 1 && flow > 0)
{
int cut_flow = dinic_dfs(next_node, sink, MIN(min_flow, flow));
if (cut_flow > 0)
{
edge[id].flow -= cut_flow;
edge[id^1].flow += cut_flow;
return cut_flow;
}
}
}
return 0;
}
int Dinic(int source, int sink)
{
int res = 0;
while (dinic_bfs(source, sink))
{
res += dinic_dfs(source, sink, INF);
}
return res;
}
int main()
{
int T;
int Case = 1;
cin>> T;
while (T--)
{
cin>> N>> M;
edge.clear();
for (int i = 1; i <= N; i++)
{
graph[i].clear();
}
for (int i = 1; i <= M; i++)
{
int a, b, c;
cin>> a>> b>> c;
add_edge(a, b, c);
add_edge(b, a, 0);
}
int res = Dinic(1, N);
cout<< "Case "<< Case++<< ": "<< res<< endl;
}
return 0;
}