首页 > 其他分享 >P3478 [POI2008] STA-Station

P3478 [POI2008] STA-Station

时间:2024-04-11 10:01:55浏览次数:28  
标签:STA int long P3478 add Station 深度 rm 节点

题目链接:

既然让求深度之和,那么我就定义以 \(i\) 为根时深度之和为 \(f_i\),现在就是思考状态转移的问题。如果以某种手段得到了 \(f_1\),那么接下来的转移就好说了。
设 \(u\) 为当前节点,\(j\) 是当前节点的子节点。\(s_i\) 表示以 \(i\) 为根的子树中的节点数量,则 \(s_u=1+ \sum{s_j}\)。当以 \(u\) 为根转到以 \(j\) 为根时,

  • 所有在 \(j\) 的子树上的节点深度都减少了 \(1\),那么总深度和就减少了 \(s_j\)
  • 所有不在 \(j\) 的子树上的节点深度都增加了 \(1\),那么总深度和就增加了 \(n - s_j\)

由此可以得出状态转移方程:\(f_j = f_u - s_j + n - s_j = f_u + n - 2 \cdot s_j\)

因此得出思路:

  1. 先进行一次 \(\rm DFS\),求出以 \(1\) 为根时每个点的深度以及以某个节点为根时其子树中的节点总数 \(s_i\)
  2. 计算出 \(1\) 号节点的答案 \(f[1]\)
  3. 再进行一次 \(\rm DFS\),递推求出每个点的答案
#include <bits/stdc++.h>

using namespace std;
using LL = long long;

const int N = 1e6 + 5, M = N << 1;
int e[M], h[N], ne[M];
int n, idx;
LL s[N], dep[N], f[N];//f[i]表示以i为根时所有节点的深度之和,dep[i]表示以1为根时节点i的深度,s[i]表示以i为根的子树中的节点数量 

void add(int a, int b) {
	e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}

void dfs(int u, int father) {
	s[u] = 1;//根节点也算一个
	dep[u] = dep[father] + 1;
	for (int i = h[u]; i != -1; i = ne[i]) {
		int j = e[i];
		if (j == father) continue;
		dfs(j, u);
		s[u] += s[j];//加上所有子树的节点
	} 
}

void get_ans(int u, int father) {
	for (int i = h[u]; i != -1; i = ne[i]) {
		int j = e[i];
		if (j == father) continue;
		f[j] = f[u] - 2 * s[j] + n;
		get_ans(j, u);
	}
}

int main()
{
	ios::sync_with_stdio(false), cin.tie(nullptr);
	cin >> n;
	memset(h, -1, sizeof h);
	for (int i = 1; i < n; i++) {
		int a, b;
		cin >> a >> b;
		add(a, b), add(b, a);
	}
	dfs(1, -1);
	for (int i = 1; i <= n; i++) f[1] += dep[i]; 
	get_ans(1, -1); 
	
	LL ans = -1e9, id = 1;
	for (int i = 1; i <= n; i++) {
		if (f[i] > ans) {
			ans = f[i];
			id = i;
		}
	}
	cout << id;
	return 0; 
}

注:
① 转移方程题目问什么设什么先,求不出来再考虑换或者辅助一下 \(dp\)
② \(dp\) 数组要开 \(\rm long\) \(\rm long\)
③ 求 \(f_1\) 的时候只能传两个参数,所以 \(\rm dep\) 需要用数组记录

引申:
我们其实根本不需要求出每个点的深度,也即 \(\rm dep\) 数组可以不用。
通过简单证明可以发现,若定义根节点的深度为 \(1\),则所有点的深度之和等于所有点的子树大小之和。
我们可以从贡献的角度考虑:
对于一个深度为 \(k\) 的节点,它会给从它到根节点路径上所有点的子树大小提供 \(1\) 的贡献,而这条路径上的点有 \(k\) 个,证毕。

#include <bits/stdc++.h>

using namespace std;
using LL = long long;

const int N = 1e6 + 5, M = N << 1;
int e[M], h[N], ne[M];
int n, idx;
LL s[N], f[N];//f[i]表示以i为根时所有节点的深度之和,dep[i]表示以1为根时节点i的深度,s[i]表示以i为根的子树中的节点数量 

void add(int a, int b) {
	e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}

void dfs(int u, int father) {
	s[u] = 1;
	for (int i = h[u]; i != -1; i = ne[i]) {
		int j = e[i];
		if (j == father) continue;
		dfs(j, u);
		s[u] += s[j];
	} 
}

void get_ans(int u, int father) {
	for (int i = h[u]; i != -1; i = ne[i]) {
		int j = e[i];
		if (j == father) continue;
		f[j] = f[u] - 2 * s[j] + n;
		get_ans(j, u);
	}
}

int main()
{
	ios::sync_with_stdio(false), cin.tie(nullptr);
	cin >> n;
	memset(h, -1, sizeof h);
	for (int i = 1; i < n; i++) {
		int a, b;
		cin >> a >> b;
		add(a, b), add(b, a);
	}
	dfs(1, -1);
	for (int i = 1; i <= n; i++) f[1] += s[i]; 
	get_ans(1, -1); 
	
	LL ans = -1e9, id = 1;
	for (int i = 1; i <= n; i++) {
		if (f[i] > ans) {
			ans = f[i];
			id = i;
		}
	}
	cout << id;
	return 0; 
}

标签:STA,int,long,P3478,add,Station,深度,rm,节点
From: https://www.cnblogs.com/pangyou3s/p/18128160

相关文章

  • selenium-浏览器复用-Invalid Status code=403 text=Forbidden
    问题:selenium-java版本为4.1.4、4.8.2+Java8运行时报InvalidStatuscode=403text=Forbidden 运行代码:publicclassRemoteTest{publicChromeOptionsoptions;publicWebDriverdriver;@TestpublicvoidremoteTest(){options=newC......
  • CF1250A Berstagram 题解
    题面。题意描述的很清楚,这里就不多赘述。思路看题,对于每个\(a_i\),若\(b_j=a_i\),则将\(b_j\)与\(b_{j-1}\)的值调换(若\(j=1\),则序列不变)。一开始想的是最直接的暴力,复杂度为\(O(nm)\),虽然开了三秒的时限,但\(4\times10^{10}\)的数据明显不是三秒钟就能解决的,含恨倒在第......
  • 【报错】Error: https://registry.npmmirror.com.tgz: tunneling socket could not be
    报错信息:Error:https://registry.npmmirror.com/bytes/download/bytes-3.0.0.tgz:tunnelingsocketcouldnotbeestablished,cause=connectECONNREFUSED127.0.0.1:31181详细报错:Error:https://registry.npmmirror.com/bytes/download/bytes-3.0.0.tgz:tunnelingsoc......
  • OSTaskCreate与xTaskCreate【chatgpt】
     UC/OS和FreeRTOS是两个不同的实时操作系统(RTOS),它们有一些相似之处,但也有一些区别。OSTaskCreate是UC/OS中的一个函数,用于创建任务。与之类似,在FreeRTOS中也有一个相应的函数xTaskCreate用于创建任务。这两个函数的作用和用法非常相似,都用于创建并启动一个新的任务。尽管函......
  • 【大模型应用开发-FastAPI框架】(五)FastAPI 如何通过Poetry运行FastAPI应用程序
    一、概述FastAPI是一个现代、快速(高性能)的Web框架,用于构建API。Poetry是一个Python的依赖管理和打包工具,可以帮助我们更有效地管理项目的依赖和环境。在本文中,我们将介绍如何使用Poetry来运行FastAPI应用程序。二、安装FastAPI和Poetry在开始之前,我们需要先安装FastAPI和P......
  • HCL AppScan Standard v10.5.0 (Windows) - Web 应用程序安全测试
    HCLAppScanStandardv10.5.0(Windows)-Web应用程序安全测试HCLAppScanStandardv10forWindowsMultilingual请访问原文链接:HCLAppScanStandardv10.5.0(Windows)-Web应用程序安全测试,查看最新版。原创作品,转载请保留出处。作者主页:sysin.org市场领先的应用程......
  • 使用ultralytics导入YOLO报错:libcublas.so.11: symbol cublasLtGetStatusString versi
    1.问题:使用yolo的时候,fromultralyticsimportYOLO.然后报错:libcublas.so.11:symbolcublasLtGetStatusStringversionlibcublasLt.so.11notdefinedinfilelibcublasLt.so.11withlinktimereference2.解决方案:pipuninstallnvidia_cublas_cu11然后就会运行......
  • 手把手教你做阅读理解题-初中中考阅读理解解题技巧015-Explore Beautiful Lake Charle
    PDF格式公众号回复关键字:ZKYD015阅读理解技巧,在帮助读者有效获取和理解文本信息方面发挥着重要作用,熟练掌握如下6个技巧,可快速突破阅读理解1预览文章结构在开始深入阅读之前,快速浏览文章的标题、段落开头和结尾,可以迅速把握文章的主题、大致内容和结构标题通常能概括文章......
  • 批量插入和更新allowmultiqueries和rewritebatchedstatements
    mybatis的批处理(效率)之rewriteBatchedStatements和allowMultiQueries-CSDN博客Mysql批量更新的一个坑-&allowMultiQueries=true允许批量更新-CSDN博客通过设置allowmultiqueries和rewritebatchedstatements可以让我们批量插入和删除速度更快。分享removeAbandonedTimeout中间......
  • Sora开源平替 Stable Video Diffusion整合包
    Sora开源平替StableVideoDiffusion整合包StableVideoDiffusion,简称SVD,是一种基于人工智能技术的模型,由初创公司StabilityAI开发。它是基于之前发布的StableDiffusion文本转图片模型的延伸,能够通过现有的图片生成视频。这款模型在AI领域具有很大的应用潜力,可以为用户......