LCT 优化 Dinic

news/2024/10/7 9:12:31/文章来源:https://www.cnblogs.com/laijinyi/p/18449758

我觉得这东西有必要记一下,因为光是看 PPT 很难自己写出代码……具体步骤相关啥都没写。

另外学这个东西也不是很必要……

Solution

我们需要一个维护最小值、最小值编号,支持区间加的 LCT。需要支持以下操作:

  • \(find\_root(u)\)
  • \(link(u,v)\)
  • \(cut(u,v)\)
  • \(find\_min(v)\)
  • \(add(u,value)\)

(注意到只需要实现 access)

首先 BFS 步骤不变,注意从 \(t\) 倒着来。得到分层图 \(G_L\) 后,通过 DFS 增广,增广步骤如下:

  1. \(G_L\) 上的每一个点建立一棵恰好包含自己一个点的树。
  2. 设跟踪的节点为 \(v\),初始置 \(v\) 为源点 \(s\)。选择一条出边 \((v,u)\),将 \(v\) 所在树连接到 \(u\) 上,设 \(v\) 的权值为出边的边权,最后将 \(v\) 移动到当前树的根。
  3. \(v\) 没有出边,那么回溯到 \(u\),删除 \((u,v)\),如果该边是树边,则断开树上相应边。
  4. 如果 \(v=t\),找到树上对应的 \(s\sim t\) 路径,将总流量加上 \(find\_min(s)\),再将路径上所有点的权值减去增广流量,删除路径上的所有零边。重新置 \(v\) 为源点 \(s\),重复步骤 3。
  5. 如果源点 \(s\) 没有出边,所有增广结束,进行下一次分层。

Code

#include <bits/stdc++.h>
using namespace std;
#define rep(i, j, k) for (int i = (j); i <= (k); ++i)
#define reo(i, j, k) for (int i = (j); i >= (k); --i)
#define mem(a) memset(a, 0, sizeof(a))
typedef long long ll;
const int N = 1e5 + 10, M = 1e5 + 10, INF = 2147483647;
int n, m, s, t;
struct Edge {int t, n, w, del;
} e[M];
int tot = 1, h[N], cur[N];
void add(int u, int v, int w) {e[++tot] = (Edge){v, h[u], w, 0}, h[u] = cur[u] = tot;
}
void eadd(int u, int v, int w) {add(u, v, w), add(v, u, 0);
}struct LCT {int ch[N][2], fa[N], mn[N], mnid[N], add[N], val[N], id[N], lef[N];LCT() {mem(ch), mem(fa), mem(add), mem(id);}#define get(u) (u == ch[fa[u]][1])#define nrt(u) (u == ch[fa[u]][0] || u == ch[fa[u]][1])void up(int u) {mn[u] = min({mn[ch[u][0]], val[u], mn[ch[u][1]]});if (mn[u] == mn[ch[u][0]]) mnid[u] = mnid[ch[u][0]];else if (mn[u] == val[u]) mnid[u] = u;else mnid[u] = mnid[ch[u][1]];if (ch[u][0]) lef[u] = lef[ch[u][0]];else lef[u] = u;}void Add(int u, int v) {if (u) mn[u] += v, add[u] += v, val[u] += v, e[id[u]].w += v, e[id[u] ^ 1].w -= v;}void down(int u) {if (add[u]) Add(ch[u][0], add[u]), Add(ch[u][1], add[u]), add[u] = 0;}void Down(int u) {if (nrt(u)) Down(fa[u]);down(u);}void rot(int u) {int f = fa[u], g = fa[f], k = get(u);if (nrt(f)) ch[g][get(f)] = u;ch[f][k] = ch[u][!k];if (ch[u][!k]) fa[ch[u][!k]] = f;ch[u][!k] = f, fa[f] = u, fa[u] = g, up(f), up(u);}void splay(int u) {for (Down(u); nrt(u); rot(u)) if (nrt(fa[u])) rot(get(u) == get(fa[u]) ? fa[u] : u);}void access(int u) {for (int v = 0; u; v = u, u = fa[u]) splay(u), ch[u][1] = v, up(u);}int find(int u) {return access(u), splay(u), lef[u];}void Del0(int u) {for (down(u); ch[u][1] && !mn[ch[u][1]]; )u = mnid[ch[u][1]], splay(u), fa[ch[u][0]] = 0, ch[u][0] = 0, up(u);}void cut(int u) {access(u), splay(u), fa[ch[u][0]] = 0, ch[u][0] = 0, up(u);}#undef get#undef nrt
} lct;void init() {rep(i, 1, n) lct.splay(i); // 释放标记lct = LCT();rep(i, 0, n) lct.mnid[i] = lct.lef[i] = i, lct.mn[i] = lct.val[i] = INF;
}int res, dis[N], que[N];
int bfs() {memset(dis, 0, sizeof(dis));init();dis[que[1] = t] = 1;for (int L = 1, R = 1; L <= R; ++L)for (int i = h[que[L]]; i; i = e[i].n) {e[i].del = e[i ^ 1].del = 0;if (e[i ^ 1].w && !dis[e[i].t])dis[que[++R] = e[i].t] = dis[que[L]] + 1;}if (!dis[s]) return 0;memcpy(cur, h, sizeof(cur));return 1;
}int dfs(int u) {if (u == t) {lct.access(s), lct.splay(t);int ret = lct.mn[t];res += ret;lct.add[t] -= ret;lct.Del0(t);return 1;}for (int &i = cur[u]; i; i = e[i].n) {int v = e[i].t;if (e[i].w && dis[v] == dis[u] - 1 && !e[i].del) {lct.splay(u), lct.fa[u] = v, lct.val[u] = e[i].w, lct.id[u] = i, lct.up(u);if (dfs(lct.find(u))) return 1;}}for (int i = h[u]; i; i = e[i].n) {int v = e[i].t;if (dis[v] == dis[u] + 1) {if (lct.find(v) == u)lct.cut(v);e[i ^ 1].del = 1;}}return 0;
}int main() {ios::sync_with_stdio(false), cin.tie(nullptr);cin >> n >> m >> s >> t;rep(i, 1, m) {int u, v, w;cin >> u >> v >> w;eadd(u, v, w);}while (bfs()) while (dfs(lct.find(s)));cout << res << '\n';return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/809319.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java之使用CompletableFuture入门2

Java 17 -序章 本文介绍用过的 allOf、anyOf 函数的用法。allOf 函数原型两点: 1、没有返回值。 2、参数 cfs 中 任何一个 都不能是 null。anyOf 函数原型两点: 1、有返回值,为 Object。 2、参数 cfs 中 任何一个 都不能是 null。allOf 测试意图: 多个任务正常执行。ben发布…

VMware Aria Operations for Logs 8.18 发布,新增功能概览

VMware Aria Operations for Logs 8.18 发布,新增功能概览VMware Aria Operations for Logs 8.18 - 集中式日志管理 请访问原文链接:https://sysin.org/blog/vmware-aria-operations-for-logs/,查看最新版。原创作品,转载请保留出处。 作者主页:sysin.org集中式日志管理 V…

VMware Aria Operations for Networks 6.13 发布,新增功能概览

VMware Aria Operations for Networks 6.13 发布,新增功能概览VMware Aria Operations for Networks 6.13 - 网络和应用监控工具 请访问原文链接:https://sysin.org/blog/vmware-aria-operations-for-networks/,查看最新版。原创作品,转载请保留出处。 作者主页:sysin.org…

读数据工程之道:设计和构建健壮的数据系统01数据工程概述

数据工程概述1. 数据工程 1.1. 自从公司开始使用数据做事,数据工程就以某种形式存在了1.1.1. 预测性分析、描述性分析和报告1.2. 数据工程师获取数据、存储数据,并准备数据供数据科学家、分析师和其他人使用 1.3. 数据工程是系统和流程的开发、实施和维护,这些系统和流程接收…

安装socks5的一次尝试

1. 下载并自动配置socks5sudo wget https://ap-guangzhou-1257892306.cos.ap-guangzhou.myqcloud.com/asi/httpsocks5.sh && sh httpsocks5.sh 执行下载脚本 wget —no-check-certificate https://raw.github.com/Lozy/danted/master/install.sh -O install.sh执行安装…

形函数的构造7

形函数构造 构造单元1的一般近似函数 \(\overline{V(x)}^{(1)}\),由于该单元只有两个节点\(x_1\)和\(x_2\),我们选择包含两个参数\(\alpha_1\)和\(\alpha_2\)的近似方程 \[\overline{V(x)}^{(1)}=\alpha_1+\alpha_2\times x \]令试函数与\(V(x)\)在节点\(x_1\)和\(x_2\)处相等…

等参单元4

在自然坐标系中 , \(\xi_2=1\)和 \(\xi_2=1\),在物理坐标系中为 \(x_1\) 和\(x_2\),相应的节点位移为\(u_1\) 和\(u_2\) 。 在自然坐标系 下,单元形函数为 \[N_{1}(\xi)=\frac{1}{2}(1-\xi)\\N_{2}(\xi)=\frac{1}{2}(1+\xi) \] 利用形函数,在自然坐标系下单元内的任一点 \(…

二维或三维的分布积分方法(格林公式)7

二维或三维的分布积分(格林公式) 分布积分对下式积分 \[\int\int_{\Omega}\Phi\frac{\partial\Psi}{\partial x}\mathrm{d}x\mathrm{d}y \] 首先对变量\(x\)分布积分 \[\int\limits_{X_L}^{X_R}U\mathrm{d}V=(UV_{X=X_R}-UV_{X=X_L})-\int\limits_{X_L}^{X_R}V\mathrm{d}U \]…

流体力学8-3

第一章 1.1 流体的概念 任何固体材料都有一个强度极限,即使合外力和力矩都为零,它的内部也可能会存在着拉力、压力或者剪切力。当这些内应力超过了材料的强度极限时,固体就会被破坏,从而产生运动。微观上体现为断裂处的分子(或原子)之间的化学键被破坏,失去了相互的作用…

应力分析7

目录3.1 几个基本概念3.3 任意斜截面上的应力3.4 主应力及应力(张量)不变量3.5 最大、最小正应力和最大剪应力 3.1 几个基本概念 • 外力 外力指的是我们熟知的机械力、电磁力等,物体因外力作用而变形。作用于物体的外力可分为体积力和表面 力,它们分别简称为体力和面力。…

塑性力学本构模型基本框架7

目录一. 引言二. 塑性应变增量推导三. 弹塑性刚度矩阵推导四. 塑性模量理解五. 小结 一. 引言 弹塑性理论定义材料在荷载作用下的变形是弹性变形和塑性变形之和,其中研究塑性变形需要解决三个方面的问题: ①产生塑性变形的起点; ②产生塑性变形的方向; ③产生塑性变形的大小…