[GESP202509 六级] 货物运输(含视频)

视频讲解:GESP202509 六级 货物运输-信息学奥赛GESP等级考试真题解析

一、原题

题目描述

A 国有 n 座城市,依次以 1,2,...,n 编号,其中 1 号城市为首都。这 n 座城市由 n−1 条双向道路连接,第 i 条道路(1≤i<n)连接编号为 ui​,vi​ 的两座城市,道路长度为 li​。任意两座城市间均可通过双向道路到达。

现在 A 国需要从首都向各个城市运送货物。具体来说,满载货物的车队会从首都开出,经过一座城市时将对应的货物送出,因此车队需要经过所有城市。A 国希望你设计一条路线,在从首都出发经过所有城市的前提下,最小化经过的道路长度总和。注意一座城市可以经过多次,车队最后可以不返回首都。

输入格式

第一行,一个正整数 n,表示 A 国的城市数量。

接下来 n−1 行,每行三个正整数 ui​,vi​,li​,表示一条双向道路连接编号为 ui​,vi​ 的两座城市,道路长度为 li​。

输出格式

一行,一个整数,表示你设计的路线所经过的道路长度总和。

输入输出样例

输入 #1

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

输出 #1

复制代码
18

输入 #2

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

输出 #2

复制代码
9

说明/提示

对于 30% 的测试点,保证 1≤n≤8。

对于另外 30% 的测试点,保证仅与一条双向道路连接的城市恰有两座。

对于所有测试点,保证 1≤n≤10^5,1≤ui​,vi​≤n,1≤li​≤10^9。

二、做题思路

1)填充数据

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
struct node{
	int to,l;
};
map<int,vector<node>>g;
int main(){
	//1)填充数据
	//1.1)确定结点数量
	int n;cin>>n;
	//1.2)填充每条道路信息
	for(int i=1;i<=n-1;i++){
		int u,v,l;cin>>u>>v>>l;
		g[u].push_back({v,l});
		g[v].push_back({u,l});
	}
	return 0; 
}

2)深搜

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
struct node{
	int to,l;
};
map<int,vector<node>>g;
bool vis[100005];
//2.2)深搜每个结点
void dfs(int x,long long now){
	vis[x]=1;
	for(auto it:g[x]){
		if(vis[it.to]==0){
			dfs(it.to,now+it.l);
		} 
	} 
}
int main(){
	//1)填充数据
	//...
	//2)深搜
	//2.1)从结点1开始 
	dfs(1,0);
	return 0; 
}

3)计算每条路径的权重,找最大

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
struct node{
	int to,l;
};
map<int,vector<node>>g;
bool vis[100005];
long long maxx=LLONG_MIN;
//2.2)深搜每个结点
void dfs(int x,long long now){
	//3)计算每条路径的权重,找最大 
	//叶子结点,证明到最底下了
	//只链接1个结点,且访问 
	if(g[x].size()==1&&vis[g[x][0].to]==1){
		maxx=max(now,maxx);
		return ; 
	} 
	vis[x]=1;
	for(auto it:g[x]){
		if(vis[it.to]==0){
			dfs(it.to,now+it.l);
		} 
	} 
}
int main(){
	//1)填充数据
	//...
	//2)深搜
	//2.1)从结点1开始 
	dfs(1,0);
	return 0; 
}

4)计算总长

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
struct node{
	int to,l;
};
map<int,vector<node>>g;
bool vis[100005];
long long maxx=LLONG_MIN;
long long total=0;
//2.2)深搜每个结点
void dfs(int x,long long now){
	vis[x]=1;
	//3)计算每条路径的权重,找最大 
	//...
	for(auto it:g[x]){
		if(vis[it.to]==0){
			dfs(it.to,now+it.l);
			//4)计算总长
			total+=it.l;
		} 
	} 
}
int main(){
	//1)填充数据
	//...
	//2)深搜
	//2.1)从结点1开始 
	dfs(1,0);
	return 0; 
}

5)最优解:(总长-最大)*2+最大

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
struct node{
	int to,l;
};
map<int,vector<node>>g;
bool vis[100005];
long long maxx=LLONG_MIN;
long long total=0;
//2.2)深搜每个结点
void dfs(int x,long long now){
	vis[x]=1;
	//3)计算每条路径的权重,找最大 
	//...
			//4)计算总长
			//...
}
int main(){
	//1)填充数据
	//...
	//2)深搜
	//...
	//5)最优解:(总长-最大)*2+最大
	cout<<(total-maxx)*2+maxx;
	return 0; 
}

三、答案

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
struct node{
	int to,l;
};
map<int,vector<node>>g;
bool vis[100005];
long long maxx=LLONG_MIN;
long long total=0;
//2.2)深搜每个结点
void dfs(int x,long long now){
	vis[x]=1;
	//3)计算每条路径的权重,找最大 
	//叶子结点,证明到最底下了
	//只链接1个结点,且访问 
	if(g[x].size()==1&&vis[g[x][0].to]==1){
		maxx=max(now,maxx);
		return ; 
	} 
	for(auto it:g[x]){
		if(vis[it.to]==0){
			dfs(it.to,now+it.l);
			//4)计算总长
			total+=it.l;
		} 
	} 
}
int main(){
	//1)填充数据
	//1.1)确定结点数量
	int n;cin>>n;
	//1.2)填充每条道路信息
	for(int i=1;i<=n-1;i++){
		int u,v,l;cin>>u>>v>>l;
		g[u].push_back({v,l});
		g[v].push_back({u,l});
	}
	//2)深搜
	//2.1)从结点1开始 
	dfs(1,0);
	//5)最优解:(总长-最大)*2+最大
	cout<<(total-maxx)*2+maxx;
	return 0; 
}
相关推荐
ZhengEnCi9 小时前
GPT-6 Astra 爆改 Qwen 权重真有那么神吗:权重空间编程 0.016% 参数的真相
算法·架构
罗西的思考9 小时前
【轻量化复刻大模型 / KIMI K3】KDA(Kimi Delta Attention):并行
人工智能·算法·机器学习
夜不会漫长11 小时前
C++:红黑树
数据结构·算法
AI备案指南-满满12 小时前
算法备案审核不通过,一般是什么原因?
java·人工智能·算法·大模型备案·算法备案·大模型登记
Ramble_Naylor12 小时前
Rust深度解读:Send 与 Sync 的本质与线程安全边界
python·算法·rust
秋天的怀念_David12 小时前
算法一千零一夜 · 第二十三夜 电力民生写成的曲线
java·程序人生·算法
不一样的故事12612 小时前
NB/T 47013.8-2015 附录D 吸枪技术
人工智能·经验分享·算法
通问AI12 小时前
用 200 行 Python 给文档库做「上下文完整度」自检:四个可复算的检查项
算法
揽星河..12 小时前
【C语言】扫雷游戏
c语言·算法·游戏
丘山录12 小时前
本地部署 LongCat-2.5,要 7 台机器我只有 4 台
人工智能·算法