[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;
} 
相关推荐
Dumbness4 小时前
UIA 读微信群消息没有 id,怎么判断哪条是新的:后缀对齐在翻历史和撤回时整屏重报
python·算法
taka4 小时前
从 24x 到 141x:我用纯 Python 零依赖项目,扒开了 GPU 加速的性能黑洞
算法
UIU1145 小时前
P16237 [蓝桥杯 2026 省 B] 应急布线
数据结构·c++·算法·蓝桥杯
旖旎夜光5 小时前
LeetCode 315: 算右侧小于当前元素的个数(归并排序) —— 题解
c++·学习·算法·leetcode·排序算法
像风一样自由20205 小时前
2.如何用FastAPI把一个Python算法封装成HTTP服务
python·算法·fastapi
D e re k ZH5 小时前
保序回归:从 PAVA 到可并堆的单调约束优化
c++·算法·数据挖掘·回归·kotlin
青少儿编程课堂5 小时前
蓝桥杯·全国青少年信息素养大赛·电子学会Python/C++考级:字典树前缀树与单词检索统计
c++·python·算法·bfs·信息学竞赛
Nuanyt5 小时前
LeetCode Hot 100 链表专题2 3 题 (Java)
java·笔记·算法·leetcode·链表
海绵宝宝转agent6 小时前
LeetCodehot100题解
java·笔记·学习·算法·leetcode·深度优先
青少儿编程课堂6 小时前
2026蓝桥杯·全国青少年信息素养大赛·电子学会Python/C++考级:堆排序与优先队列解析
c++·python·算法·bfs·信息学竞赛