首页 > 其他分享 >LCT 优化 Dinic

LCT 优化 Dinic

时间:2024-10-07 09:12:15浏览次数:1  
标签:LCT ch int void mn fa add Dinic 优化

我觉得这东西有必要记一下,因为光是看 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;
}

标签:LCT,ch,int,void,mn,fa,add,Dinic,优化
From: https://www.cnblogs.com/laijinyi/p/18449758

相关文章

  • 全面图解Docker架构设计:掌握Docker全链路思维与优化(命令篇)
    Docker是一个革命性的开放平台,用于开发、交付和运行应用程序。通过使用Docker,开发者可以打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何支持Docker的环境中,在不同环境中实现一致的运行。无论是在虚拟机、物理服务器、数据中心还是云平台,Docker都能确保......
  • 全面图解Docker架构设计:掌握Docker全链路思维与优化(命令篇)
    Docker是一个革命性的开放平台,用于开发、交付和运行应用程序。通过使用Docker,开发者可以打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何支持Docker的环境中,在不同环境中实现一致的运行。无论是在虚拟机、物理服务器、数据中心还是云平台,Docker都能确......
  • 优化方案
    Iunderstandyou'relookingtooptimizethecoderealizationtoimproveaccuracy.Thisisanimportantgoalinmachinelearningmodeldevelopment.Let'sfocusonsomestrategiesthatcouldpotentiallyenhancethemodel'saccuracy:importto......
  • 斜率优化 DP
    斜率优化DP在单调队列优化过程中,转移方程被拆成了两部分,第一部分仅与\(j\)有关,而另一部分仅与\(i\)有关,因此我们可以利用单调队列仅维护与\(j\)有关的部分,实现问题的快速求解。但仍然有很多转移方程,\(i\)和\(j\)是紧密相关的,这个时候单调队列优化就不适用了,例如如下转......
  • MATLAB|基于多主体主从博弈的区域综合能源系统低碳经济优化调度
    目录主要内容   程序亮点:  模型研究   一、综合能源模型二、主从博弈框架  部分代码     结果一览   下载链接主要内容   程序参考文献《基于多主体主从博弈的区域综合能源系统低碳经济优化调度》,采用了区域综合能源系统多主体博弈协同优化......
  • 专业网站优化:提升在线竞争力的关键策略
    在当今数字化时代,网站优化已成为企业提升在线竞争力、吸引潜在客户和推动业务增长的重要手段。一个经过专业优化的网站不仅能够提高搜索引擎排名,还能显著提升用户体验,从而为企业带来持续稳定的流量和收益。本文将深入探讨专业网站优化的核心策略与实践方法,帮助企业更好地利用......
  • 全面图解Docker架构设计:掌握Docker全链路思维/实战/优化(小白到大师篇[2])
    Docker是一个革命性的开放平台,用于开发、交付和运行应用程序。通过使用Docker,开发者可以打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何支持Docker的环境中,在不同环境中实现一致的运行。无论是在虚拟机、物理服务器、数据中心还是云平台,Docker......
  • 斜率优化学习笔记
    斜率优化模板题,有三倍经验,难度逐渐递增,建议从前做到后。P2365任务安排,P10979任务安排2,P5785[SDOI2012]任务安排。(但是我这种做法P10979和P5785没有区别。思路:设\(f_i\)表示第\(i\)个任务加工后所需的最小总费用,那么就有转移式。\[f_i=\displaystyle\min_{j=0}^{......
  • 古典舞在线交流:SpringBoot平台实现与优化
    第一章绪论1.1研究背景在当今的社会,可以说是信息技术的发展时代,在社会的方方面面无不涉及到各种信息的处理。信息是人们对客观世界的具体描述,是人们进行交流与联系的重要途径。人类社会就处在一个对信息进行有效合理的加工中。它将促进整个社会的发展。随着社会信息技术......
  • <min/max,+>卷积与背包优化
    【前置知识】convex与concave:这是对于数组的概念。类比函数,下凸就是convex,上凸就是concave。【<min,+>卷积问题】考虑两个数组\(a_{1\simn},b_{1\simm}\),定义它们的<min,+>卷积结果\(c\):\(|c|=n+m\)。\(c_i=\min_{j+k=i}\{a_j+b_k\}\)。因为普通的卷积是\(\s......