[GESP202609 六级] 分树规划

视频讲解:GESP202512 六级 分树规划-信息学奥赛GESP等级考试真题解析

一、原题

题目描述

老师有一棵有 n 个结点的树,结点依次以 1,2,...,n 编号。

老师想将这棵树作为奖品分给两位同学。具体而言,老师会选择一条边并从树上删去它,从而将这棵树分为两个连通块。两位同学分别可以得到其中一个连通块。

如果有同学拿到的连通块结点数明显小于另一位同学,那么这位同学会不太高兴。为了避免这种情况出现,老师想知道两个连通块结点数之差的绝对值最小是多少。

输入格式

第一行,一个正整数 n,表示结点数量。

接下来 n−1 行,每行两个正整数 ui​,vi​,表示一条连接结点 ui​ 和结点 vi​ 的边。

输出格式

输出一行,一个整数,表示答案。

输入输出样例

输入 #1

复制代码
4
1 2
2 3
3 4

输出 #1

复制代码
0

输入 #2

复制代码
6
1 2
1 3
1 4
1 5
5 6

输出 #2

复制代码
2

说明/提示

对于 40% 的测试点,保证 2≤n≤500。

对于所有测试点,保证 2≤n≤2×10^4。

二、做题思路

1)邻接表构造树

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
int n;
map<int,vector<int>>g;
int main(){
	//1)邻接表构造树
	//1.1)确定结点数量
	cin>>n;
	//1.2)填充n-1条边的
	for(int i=1;i<=n-1;i++){
		int u,v;cin>>u>>v;
		g[u].push_back(v);
		g[v].push_back(u);
	} 
} 

2)深搜计算每个结点的结点数量(包括自身)

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
int n;
map<int,vector<int>>g;
bool vis[20004];
int c[20004];
//2)深搜函数 :计算每个结点的结点数(包括自身)
void dfs(int x){
	//2.1)标记访问 
	vis[x]=1;
	//2.2)搜索每个子节点
	for(auto it:g[x]){
		if(vis[it]==0){
			dfs(it);
			//2.3)累加当前子节点数
			c[x]+=c[it];
		} 
	} 
	//2.4)自身也算 
	c[x]++;
}
int main(){
    //1)邻接表构造树
    //....
	//2)深搜计算每个结点的结点数(包括自身)
	dfs(1);
} 

3)找每条边,左右结点数之差的绝对值最小

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
int ans=INT_MAX;
void dfs(int x){
	//...
	//3)找每条边,左右结点数之差的绝对值最小
	ans=min(ans, abs(c[x]-(n-c[x])) );
}
int main(){
	//...
    cout<<ans;
} 

三、答案

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
int n;
map<int,vector<int>>g;
bool vis[20004];
int c[20004];
int ans=INT_MAX;
//2)深搜函数 :计算每个结点的结点数(包括自身)
void dfs(int x){
	//2.1)标记访问 
	vis[x]=1;
	//2.2)搜索每个子节点
	for(auto it:g[x]){
		if(vis[it]==0){
			dfs(it);
			//2.3)累加当前子节点数
			c[x]+=c[it];
		} 
	} 
	//2.4)自身也算 
	c[x]++;
	//3)找每条边,左右结点数之差的绝对值最小
	ans=min(ans, abs(c[x]-(n-c[x])) );
}
int main(){
	//1)邻接表构造树
	//1.1)确定结点数量
	cin>>n;
	//1.2)填充n-1条边的
	for(int i=1;i<=n-1;i++){
		int u,v;cin>>u>>v;
		g[u].push_back(v);
		g[v].push_back(u);
	} 
	//2)深搜计算每个结点的结点数(包括自身)
	dfs(1);
	
	cout<<ans;
} 
相关推荐
夏幻灵1 小时前
LeetCode 21:合并两个有序链表——双指针与哑节点详解
算法·leetcode·链表
徐小黑ACG3 小时前
Golang 基础05 结构体struct
开发语言·算法·golang
Navigator_Z3 小时前
LeetCode //C - 1286. Iterator for Combination
c语言·算法·leetcode
北极有牛4 小时前
cpp学习笔记--常量指针
java·开发语言·算法
GPU实战笔记4 小时前
云端 GPU 训练的账户余额提醒:它能说明什么,不能说明什么?
深度学习·算法·成本管理·gpu云计算·云端训练
浮链序4 小时前
怎么证明"你这个模型是偷我的"——把蒸馏变成取证工具
算法·安全·llm
小O的算法实验室4 小时前
IEEE TMC,面向异构物联网的多目标量子行为拓扑优化算法
算法
liliangcsdn5 小时前
派息率指标的应用探索和分析
大数据·算法