嗯,将两个放在一起的原因…只是因为单另分开篇幅不够罢。
绝对不是因为例题只有BZOJ1001什么的
最小割最大流定理
搜了一圈没有找到什么是最小割,然后懵逼了。
嗯……
首先,什么是割?其实,割=割边=去掉以后使图不连通的边的集合
然后,容量和最少的割集称为最小割。
对于割,有这样一个重要定理:
最小割=最大流
嗯,最小割就这么多东西。
为什么正确?这里给出一种直观的想法
(原PO:https://jecvay.com/2014/11/what-is-min-cut.html)
1.最大流不可能大于最小割, 因为最大流所有的水流都一定经过最小割那些割边, 流过的水流怎么可能比水管容量还大呢?
2.最大流不可能小于最小割, 如果小, 那么说明水管容量没有物尽其用, 可以继续加大水流.
证毕。
先来看一道例题,十分经典的BZOJ1001
这里首先说一个技巧,无向图的网络流在建边时反向弧也直接建成权值为v即可
题意是求一个无向图的最小割,然后我们运用最小割-最大流定理,可以转化成求最大流的问题。不过朴素的Dinic是会TLE的,这里提供一种优化方法:
我们知道,假定在一次dinic过程中,发现不能再进行增广了,那么就相当于向下的这条路是废的。因此,我们可以直接把这条路堵上,然后就可以过了。优化效果很明显,TLE->1644msAC(虽然我质疑出题人可能专门卡了朴素的Dinic)
#include <iostream>
#include <cstdio>
#include <queue>
#include <cstring>
#include <cctype>
using namespace std;
inline void read(int &x) {
x = 0; char c = getchar();
while(!isdigit(c)) c = getchar();
while(isdigit(c)) x = (x << 3) + (x << 1) + c - '0', c = getchar();
}
#define MAXN 1003
struct node{
int fr, to, va, nxt;
}edge[MAXN * MAXN * 6];
int head[MAXN * MAXN], cnt;
inline void add_edge(int u, int v, int w) {
edge[cnt].fr = u, edge[cnt].to = v, edge[cnt].va = w;
edge[cnt].nxt = head[u], head[u] = cnt++;
edge[cnt].fr = v, edge[cnt].to = u, edge[cnt].va = w;
edge[cnt].nxt = head[v], head[v] = cnt++;
}
int st, ed, rank[MAXN * MAXN];
int BFS() {
queue<int> q;
memset(rank, 0, sizeof rank);
rank[st] = 1;
q.push(st);
while(!q.empty()) {
int<