首页 > 其他分享 >换根DP

换根DP

时间:2023-05-28 10:44:06浏览次数:43  
标签:head idx int next fa 换根 DP deg

换根法思路:

  1. 自下而上递推;
  2. 自上而下递推。

P3478 [POI2008] STA-Station

首先使用 \(\text{dfs}\) 求出以每个节点 \(u\) 为根的子树大小 \(s[u]\)。

然后我们设 \(f[i]\) 为以 \(i\) 为根时所有节点的深度之和,\(j\) 为 \(i\) 的子节点。

那么对于所有 \(j\) 的子节点,深度都减 \(1\),所以总共减少了 \(s[j]\)。

对于所有不是 \(j\) 的子节点的节点,深度都加 \(1\) ,所以总共加了 \(n - s[j]\)。

所以 \(f[j] = f[i] - s[j] + n - s[j] = f[i] + n - 2 \times s[j]\)。

最后取 \(\max\) 即可。

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;
using i64 = long long;

const int N = 1000010;

struct Edge {
	int to, next;
}e[N * 2];

int head[N], idx;

void add(int a, int b) {
	idx++;
	e[idx].to = b;
	e[idx].next = head[a];
	head[a] = idx;
}

int n;
int sz[N];

void dfs1(int u, int fa) {
	sz[u] = 1;
	for (int i = head[u]; i; i = e[i].next) {
		int to = e[i].to;
		if (to == fa) continue;
		dfs1(to, u);
		sz[u] += sz[to];
	}
}

int f[N];
int maxv, ans;

void dfs2(int u, int fa) {
	for (int i = head[u]; i; i = e[i].next) {
		int to = e[i].to;
		if (to == fa) continue;
		f[to] = f[u] + n - 2 * sz[to];
		dfs2(to, u);
	}
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);

	cin >> n;
	for (int i = 1; i < n; i++) {
		int x, y;
		cin >> x >> y;
		add(x, y);
		add(y, x);
	}
	dfs1(1, 0);
	for (int i = 1; i <= n; i++) f[1] += sz[i];
	dfs2(1, 0);
	for (int i = 1; i <= n; i++) if (f[i] > maxv) maxv = f[i], ans = i;
	cout << ans << '\n';
	return 0;
}

AcWing 287. 积蓄程度 / POJ 3585 Accumulation Degree

设 \(d[i]\) 表示 \(i\) 点可以向下传递的最大流量。

设 \(f[i]\) 表示 \(i\) 点可以向外传递的最大流量(包括向下流的流量和向上流的流量)。

先 \(\text{dfs}\) 一遍求出 \(d\)。

有:

如无特殊说明 \(to\) 表示 \(i\) 的子节点,\(edge(i, to)\) 表示 \(i\) 和 \(to\) 这条边的最大流量。

\(d[i] = \sum \min(d[to], edge(i, to))\)

\(f[to] = \min(edge(i, to), f[i] - \min(edge(i, to), d[to]))\)

同时注意如果根的度为 \(1\)(如下图) ,那么计算它的子节点时要采用公式:

\(f[i] = f[to] + edge(i, to)\)

image

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 200010, INF = 0x3f3f3f3f;

struct Edge {
	int to;
	int next;
	int w;
}e[N * 2];

int head[N], idx, deg[N];

void add(int a, int b, int c) {
	idx++;
	e[idx].to = b;
	e[idx].next = head[a];
	e[idx].w = c;
	head[a] = idx;
}

int n;
int f[N], d[N];

int dfs1(int u, int fa) {
	for (int i = head[u]; i; i = e[i].next) {
		int to = e[i].to;
		if (to == fa) continue;
		d[u] += min(dfs1(to, u), e[i].w);
	}
	if (deg[u] == 1) return INF;
	return d[u];
}

void dfs2(int u, int fa) {
	for (int i = head[u]; i; i = e[i].next) {
		int to = e[i].to;
		if (to == fa) continue;
		if (deg[u] == 1) f[to] = d[to] + e[i].w;
		else f[to] = d[to] + min(e[i].w, f[u] - min(d[to], e[i].w));
		dfs2(to, u);
	}
}

void solve() {
	idx = 0;
	memset(head, 0, sizeof(head));
	memset(deg, 0, sizeof(deg));
	memset(f, 0, sizeof(f));
	memset(d, 0, sizeof(d));
	cin >> n;
	for (int i = 1; i < n; i++) {
		int x, y, z;
		cin >> x >> y >> z;
		add(x, y, z);
		add(y, x, z);
		deg[x]++;
		deg[y]++;
	}
	dfs1(1, 0);
	f[1] = d[1];
	dfs2(1, 0);
	int ans = 0;
	for (int i = 1; i <= n; i++) ans = max(ans, f[i]);
	cout << ans << '\n';
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);

	int T;
	cin >> T;
	while (T--) solve();

	return 0;
}

标签:head,idx,int,next,fa,换根,DP,deg
From: https://www.cnblogs.com/PlayWithCPP/p/17437892.html

相关文章

  • Unity的IPostBuildPlayerScriptDLLs:深入解析与实用案例
    UnityIPostBuildPlayerScriptDLLsUnityIPostBuildPlayerScriptDLLs是Unity引擎中的一个非常有用的功能,它可以让开发者在构建项目后自定义哪些文件需要被复制到输出目录中。这个功能可以帮助开发者更好地控制项目的构建过程,确保输出目录只包含必要的DLL文件。在本文中,我们将介绍U......
  • wordpress插件:用WP Media Category Management管理媒体库分类
    一,安装插件:搜索WPMediaCategoryManagement点击立即安装 安装完成后,点击启用点击启用后页面会报错,忽略它返回前一个页面,点这里:提示要自动更新,跳过,也可选允许并继续按默认设置,点SaveSettings二,应用插件:1,添加分类2,修改图片所属分类3,从媒体库选择时:......
  • Unity的IPostBuildPlayerScriptDLLs:深入解析与实用案例
    UnityIPostBuildPlayerScriptDLLsUnityIPostBuildPlayerScriptDLLs是Unity引擎中的一个非常有用的功能,它可以让开发者在构建项目后自定义哪些文件需要被复制到输出目录中。这个功能可以帮助开发者更好地控制项目的构建过程,确保输出目录只包含必要的DLL文件。在本文中,我们将介绍......
  • Unity的BuildPlayerProcessor:深入解析与实用案例
    UnityBuildPlayerProcessorUnityBuildPlayerProcessor是Unity引擎中的一个非常有用的功能,它可以让开发者在构建项目时自动执行一些操作。这个功能可以帮助开发者提高工作效率,减少手动操作的时间和错误率。在本文中,我们将介绍UnityBuildPlayerProcessor的使用方法,并提供三个使用......
  • 2023华为伙伴大会:ISDP发布伙伴体验中心,邀伙伴探索数智化未来
    近日,2023年华为中国合作伙伴大会于深圳国际会展中心(宝安)圆满落幕。本次大会向来自全国各个领域的1.6万多名华为新老朋友,提供一个面对面开放交流、自我展示的舞台。此次大会煤亮子、软通动力、中软国际、易宝、全采智能等多家ISDP的新老伙伴出席,一起交流行业发展与下一步合作。其中......
  • 华为ISDP:从ChatGPT说起,企业作业数字化转型需要怎样的平台工具?
    在各行各业轰轰烈烈的数字化转型浪潮中,企业一方面需要实现自身数字化转型以向客户提供更好的业务体验,提升效率,另一方面需要发挥数字化杠杆作用使能企业成本降低,增强行业竞争力。在2023年第20届华为分析师大会开幕式上,华为轮值董事长孟晚舟分享了分享数字化转型三个核心洞见,她指出华......
  • m基于SPA和积译码算法的LDPC误码率matlab仿真
    1.算法仿真效果matlab2022a仿真结果如下: 2.算法涉及理论知识概要       LDPC(Low-densityParity-check,低密度奇偶校验)码是由Gallager在1963年提出的一类具有稀疏校验矩阵的线性分组码(linearblockcodes),然而在接下来的30年来由于计算能力的不足,它一直被人......
  • 数学期望DP学习笔记
    数学期望:在概率论和统计学中,数学期望(mathematicexpectation)(或均值,亦简称期望)是试验中每次可能结果的概率乘以其结果的总和,是最基本的数学特征之一。它反映随机变量平均取值的大小。——摘自百度百科不懂?太正常了,百度百科就是不写人话。举个栗子解释一下:下面看一道例题:蓝桥......
  • expdp 导出缓慢
    expdp导出缓慢查询等待事件,目前导出的等待事件是:selectinst_id,sql_id,event,count(*)fromgv$sessionwherewait_class<>'Idle'groupbyinst_id,sql_id,eventorderbycount(*)desc;INST_IDEVENTCOUNT(1)---------......
  • 2023华为伙伴大会:ISDP发布伙伴体验中心,邀伙伴探索数智化未来​
    近日,2023年华为中国合作伙伴大会于深圳国际会展中心(宝安)圆满落幕。本次大会向来自全国各个领域的1.6万多名华为新老朋友,提供一个面对面开放交流、自我展示的舞台。此次大会煤亮子、软通动力、中软国际、易宝、全采智能等多家ISDP的新老伙伴出席,一起交流行业发展与下一步合作。其中......