博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
BZOJ2229: [Zjoi2011]最小割(最小割树)
阅读量:6007 次
发布时间:2019-06-20

本文共 3703 字,大约阅读时间需要 12 分钟。

最小割树

算法

初始时把所有点放在一个集合

从中任选两个点出来跑原图中的最小割
然后按照 \(s\) 集合与 \(t\) 集合的归属把当前集合划分成两个集合,递归处理
这样一共跑了 \(n − 1\) 次最小割
可以证明图中任意一对点之间的最小割的数值都包含在这 \(n − 1\) 个数值当中
把每次求出的最小割看成是两个点之间的边,可以建出一棵树

定理1

任意三点之间的最小割一定是两个相等的较小值和一个较大值

证明

设任意三点 \(a, b, c\) 之间的最小割分别为 \(mincut(a, b), mincut(a, c), mincut(b, c)\)
\(mincut(a, b)\) 是这三者中的最小值
那么在做 \(a − b\) 割时,\(c\) 一定属于其中的某一个集合,设其与 \(a\) 同属于一个集合
那么就有 \(mincut(b, c) \le mincut(a, b)\)
又因为 \(mincut(a, b) \le mincut(b, c)\),所以两者相等

定理2

图中至多只有 \(n − 1\) 种不同的最小割

证明

编了一个构造的证明
首先根据定理 \(1\) ,可以转化成如下问题:

\(n\) 个点的无向完全图,要给每一条边染色,要求每个三元环上有两条边同色,求最多可以染多少种颜色

考虑归纳法

假设现在已经有一条长度大于 \(1\) 的链 \(a\)\(b\) 上的边的颜色互不相同
考虑染 \((a,b)\) 这条边
如果链长 \(=2\),那么 \((a,b)\) 只能选择链上某条边的颜色
如果链长 \(>2\),假设两个端点在链上的不是 \((a,b)\) 的边的颜色都是链上某条边的颜色
那么取出其中两条 \((a,c)\)\((c,b)\)\((a,b)\) 只能选择两个中其中一条边的颜色,即链上某条边的颜色

所以可以得到,颜色互不相同的边不能形成环,所以最优的显然是树,即 \(n-1\) 中颜色

Sol

至此问题已经完美解决

建出最小割树,任意两个点的最小割就是路径边权最小值
直接暴力也可以
复杂度貌似 \(\Theta(n^3m)\) \(???\)

# include 
using namespace std;typedef long long ll;const int maxn(505);const int inf(1e9);int first[maxn], n, m, cnt, lev[maxn], vis[maxn], s, t, id[maxn], tmp[maxn], cur[maxn], mincut[maxn][maxn], record[maxn << 4];queue
q;struct Edge { int to, next, w;} edge[maxn << 4];inline void Add(int u, int v, int w) { edge[cnt] = (Edge){v, first[u], w}, first[u] = cnt++; edge[cnt] = (Edge){u, first[v], w}, first[v] = cnt++; record[cnt - 1] = record[cnt - 2] = w;}inline int Bfs() { memset(lev, 0, sizeof(lev)), lev[s] = 1, q.push(s); register int u, e, v; while (!q.empty()) { for (u = q.front(), q.pop(), e = first[u]; ~e; e = edge[e].next) if (edge[e].w && !lev[v = edge[e].to]) lev[v] = lev[u] + 1, q.push(v); } return lev[t];}int Dfs(int u, int maxf) { if (u == t) return maxf; register int ret = 0, &e = cur[u], f, v; for (; ~e; e = edge[e].next) if (edge[e].w && lev[v = edge[e].to] == lev[u] + 1){ f = Dfs(v, min(edge[e].w, maxf - ret)); ret += f, edge[e].w -= f, edge[e ^ 1].w += f; if (ret == maxf) return ret; } if (!ret) lev[u] = 0; return ret;}inline int Dinic() { register int ret = 0, i; for (i = 0; i < cnt; ++i) edge[i].w = record[i]; while (Bfs()) memcpy(cur, first, sizeof(cur)), ret += Dfs(s, inf); return ret;}void Mark(int u) { if (vis[u]) return; register int e; for (vis[u] = 1, e = first[u]; ~e; e = edge[e].next) if (edge[e].w) Mark(edge[e].to);}inline void Solve(int l, int r) { if (l >= r) return; memset(vis, 0, sizeof(vis)), s = id[l], t = id[r]; register int i, j, mid, d = Dinic(); for (Mark(s), j = 0, i = l; i <= r; ++i) if (vis[id[i]]) tmp[++j] = id[i]; for (mid = l + j - 1, i = l; i <= r; ++i) if (!vis[id[i]]) tmp[++j] = id[i]; for (i = l; i <= r; ++i) id[i] = tmp[i - l + 1]; for (i = 1; i <= n; ++i) if (vis[i]) for (j = 1; j <= n; ++j) if (i != j && !vis[j]) mincut[i][j] = mincut[j][i] = min(mincut[i][j], d); Solve(l, mid), Solve(mid + 1, r);}int main() { register int i, j, u, v, w, test; scanf("%d", &test); while (test--) { memset(first, -1, sizeof(first)), cnt = 0; scanf("%d%d", &n, &m); for (i = 1; i <= m; ++i) scanf("%d%d%d", &u, &v, &w), Add(u, v, w); for (i = 1; i <= n; ++i) id[i] = i; memset(mincut, 63, sizeof(mincut)), Solve(1, n), scanf("%d", &w); while (w--) { scanf("%d", &u), v = 0; for (i = 1; i <= n; ++i) for (j = i + 1; j <= n; ++j) v += mincut[i][j] <= u; printf("%d\n", v); } putchar('\n'); } return 0;}

参考文献

  1. 某鸽姓选手的网络流课件
    2. 垃圾博主自己yy

转载于:https://www.cnblogs.com/cjoieryl/p/10091155.html

你可能感兴趣的文章
【Java】Socket+多线程实现控制台聊天室
查看>>
CAD注记层转到SDE Annotation Features(ArcEngine,C++实现)(转载)
查看>>
easyui datagrid 列的内容超出所定义的列宽时,自动换行
查看>>
【USACO 2.3】Controlling Companies (递推)
查看>>
ABP文档 - 审计日志
查看>>
前端Html和Css面试题
查看>>
spring可以get到bean,注入却为空
查看>>
Nginx+PHP-FPM优化技巧总结
查看>>
python易错盲点排查之+=与+的区别分析以及一些赋值运算踩过的坑
查看>>
RFID应用范围
查看>>
智力杠杆
查看>>
解决IE6-IE8 Js代码不执行问题
查看>>
iOS9横竖屏设置的处理方法
查看>>
View坐标系详解(getTop(),getLeft(),getX(),getY(),getLocationOnScreen(), getLocationInWindow())
查看>>
学习ASP.NET Core Razor 编程系列三——创建数据表及创建项目基本页面
查看>>
golang编译库文件方式
查看>>
一道笔试题:捞鱼问题
查看>>
SUSE的SSHD配置及设置防火墙
查看>>
jQuery实现右上角点击后滑下来的竖向菜单
查看>>
信息加密之消息摘要算法的SHA
查看>>