最大流
最大流大概是网络流最基础的内容,可能也是最常考的内容。T_T
可行流和最大流
可行流是网络流的基础概念,严谨定义如下:
如果有一组流量满足条件:
源点S: 流出量 = 整个网络的流量
汇点T: 流入量 = 整个网络的流量
中间点: 总流入量 = 总流出量
那么整个网络中的流量成为一个可行流。
最大流,顾名思义就是最大的可行流。当然最大流可能不止一个,我们求出的是最大流的值(当然只有一个,要不然就不是最大的了)。
话说最大流一共有三种常用算法:Dinic, SAP, 预流推进。具体哪种最快是玄学,三种貌似都可以构造出卡掉的数据。
目前Dinic和SAP已成为OI界两大邪教。当然Dinic要加当前弧优化,SAP要加gap优化。
不过就我个人看Dinic很少被卡,可能是写Dinic的人很多吧。
记下Dinic模版,略显丑陋但是实用。
代码
namespace MaxFlow
{
const int MAXN = 100005 , MAXNODE = 200005 , MAXEDGE = 1600005 , INF = 0x3f3f3f3f;
int edge[MAXEDGE][3] , head[MAXNODE] , maxe = 2;
int len[MAXNODE] , cur[MAXNODE];
void init()
{
maxe = 2;
memset(head, 0, sizeof(head));
}
bool bfs(int s , int t)
{
memset(len, -1, sizeof(len));
len[t] = 1;
queue<int> que;
que.push(t);
while (que.size())
{
int u = que.front();
que.pop();
for (int i = head[u] ; i ; i = edge[i][2])
if (len[edge[i][0]] == -1 && edge[i ^ 1][1])
{
len[edge[i][0]] = len[u] + 1;
que.push(edge[i][0]);
}
}
return len[s] != -1;
}
int dfs(int p , int maxf , int u)
{
if (p == u) return maxf;
int res = 0 , tmp = 0;
if (cur[p] == -1) cur[p] = head[p];
for (; res < maxf && cur[p] ; cur[p] = edge[cur[p]][2])
if (len[edge[cur[p]][0]] + 1 == len[p] && edge[cur[p]][1])
{
tmp = dfs(edge[cur[p]][0], min(maxf - res, edge[cur[p]][1]), u);
res += tmp;
edge[cur[p]][1] -= tmp;
edge[cur[p] ^ 1][1] += tmp;
if (res >= maxf) break;
}
return res;
}
int dinic(int s , int t)
{
int res = 0;
while (bfs(s, t))
{
memset(cur, -1, sizeof(cur));
res += dfs(s, INF, t);
}
return res;
}
void addEdge(int u , int v , int f)
{
edge[maxe][0] = v;
edge[maxe][1] = f;
edge[maxe][2] = head[u];
head[u] = maxe++;
edge[maxe][0] = u;
edge[maxe][1] = 0;
edge[maxe][2] = head[v];
head[v] = maxe++;
}
}