重修最小割——无向图与网络
本文同步发布至我的blog。
无向图最小割
定义是这样的:将无向图
肯定不能用网络流求。
Stoer-Wagner 算法
首先我们知道对于两点
那么最先想到的肯定是枚举
所以很容易想到如下的算法流程:
- 随便找
s,t ,求这张图的s-t 割。 - 合并
s,t ,如果此时|V|>1 ,那么回到步骤1 。 - 输出所有割中的最小值。
然后我们考虑如果求这张图的
首先我们维护一个集合
定义权值函数
每次找到
那么设最后被加入集合的点是
证明
定义节点
定义集合
定义诱导割为
则有对于任何被激活的点
证明:
采用数学归纳法。对于第一个被激活的点
对于其它两个被激活的节点
已知
时间复杂度可以近似看做
但是我好想没找到不能用网络流做的最小割。
核心代码
int Stoer_Wagner(){
int mincut = 0x3f3f3f3f;
for(int i=1;i<n;i++){
int s = 0 , t = 0;
memset(vis2,0,sizeof(vis2));
memset(w,0,sizeof(w));
for(int j=1;j<=n-i+1;j++){
int now = 0;
for(int k=1;k<=n;k++){
if(!vis1[k]&&!vis2[k]&&w[k]>=w[now])now = k;
}
s = t , t = now , vis2[now] = 1;
for(int k=1;k<=n;k++)w[k] += dis[k][now];
}
mincut = min(mincut,w[t]);
vis1[t] = 1;
for(int j=1;j<=n;j++)if(j!=s)dis[j][s] += dis[j][t] , dis[s][j] += dis[t][j];
}
return mincut;
}
网络中的最小割
最大流最小割定理
首先先引入一个引理:对于一个任意的流
为了取等,显然第一个不等号需要
然后我们来证明最大流最小割定理。
我们假设某一轮增广后不存在增广路,记所有能从
将所有边分两类讨论:
满足我们刚才提到
例题
例题 P2762
根据最小割的性质,如果割掉一条边就必须割掉另一条边,那么我们通常在它们中间连接容量为
在本题中,由于实验必须要用到仪器,所以我们可以将实验和对应仪器连一条这样的边。源点向实验连边,容量为实验的获利。仪器向汇点连边,容量为仪器的价格。割掉表示不选这个实验。
答案即为总共获利减去最小割,输出方案只用输出与源点,汇点直接连接的点即可。
例题 P1344
难点在于如何判断最小割边数。注意到我们将所有边的流量同时乘以一个数,再除回来是不影响答案的,所以我们可以根据这个性质来解题。注意到如果我们对每条边的流量都乘以一个很大的数,然后再加
这是因为我们可以把最大流看做很多流量从源点出发,最后汇聚到汇点,对于两条提前汇聚的增广路,我们只需要割掉汇聚后的一条边即可,而按我们这样建边,它的最大流量正好增加
例题 P4177
考虑割掉中间的边并不影响其它路径。这就对应了租借操作:并不会影响其它的工作。所以我们考虑把中间的边容量改为租借该机器的费用即可。