[GESP202509 六级] 货物运输

题目描述

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

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

输入格式

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

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

输出格式

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

输入输出样例 #1

输入 #1

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

输出 #1

复制代码
18

输入输出样例 #2

输入 #2

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

输出 #2

cpp 复制代码
9

说明/提示

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

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

对于所有测试点,保证 1 ≤ n ≤ 10 5 1 \le n \le 10^5 1≤n≤105, 1 ≤ u i , v i ≤ n 1 \le u_i,v_i \le n 1≤ui,vi≤n, 1 ≤ l i ≤ 10 9 1 \le l_i \le 10^9 1≤li≤109。

提交链接

https://www.luogu.com.cn/problem/P14076

思路分析

在一棵树上,如果要遍历所有节点:

  1. 每条边至少要走一次

  2. 如果需要回到起点,每条边会走两次

但本题:

最后可以不返回首都,这意味着:可以省掉"最后一条路径"的回程。

S = 所有边权之和

D = 从首都出发到某个节点的最长距离(树的最大深度)

那么答案是:2 × S − D

cpp 复制代码
void dfs(int x , ll p)
{
    vis[x] = true;
    for(auto edge : g[x])
    {
        int y = edge.first;
        ll val = edge.second;
        if(!vis[y])
        {
            dfs(y , p + val);
        }
    }
    mx = max(mx , p);
}

x x x:当前节点

p p p:从 1 1 1 号节点到当前节点的路径长度

当递归完成后:p p p 就是当前节点到根节点的距离

完整代码

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 9;
typedef long long ll;

int n;
vector< pair<int , int> >g[maxn];
ll sum , mx;
bool vis[maxn];

void dfs(int x , ll p)
{
	vis[x] = true;
	for(auto edge : g[x])
	{
		int y = edge.first;
		ll val = edge.second;
		if(!vis[y])
		{
			dfs(y , p + val);
		}
	}
	mx = max(mx , p);
}

int main()
{
	cin >> n;
	for(int i = 1; i <= n - 1; i++)
	{
		int x , y , z;
		cin >> x >> y >> z;
		sum += 2 * z;
		g[x].push_back({y , z});
		g[y].push_back({x , z});
	}
	dfs(1 , 0);
	cout << sum - mx;
    return 0;
}
相关推荐
c++逐梦人15 分钟前
记忆化搜索(DFS)
算法·深度优先
IronMurphy20 小时前
【算法三十七】51. N 皇后
算法·深度优先
im_AMBER1 天前
Leetcode 153 课程表 | 腐烂的橘子
开发语言·算法·leetcode·深度优先·图搜索
17(无规则自律)2 天前
DFS连通域统计:岛屿数量问题及其变形
c++·算法·深度优先
im_AMBER2 天前
Leetcode 152 被围绕的区域 | 岛屿数量
数据结构·算法·leetcode·深度优先·广度优先·图搜索算法
wanderist.2 天前
图论模板整理
算法·深度优先·图论
17(无规则自律)2 天前
DFS:带重复项的全排列,程序运行全流程解析
c++·算法·深度优先
散峰而望2 天前
【基础算法】动态规划从入门到进阶:记忆化搜索、线性 DP、LIS/LCS 一网打尽
c++·后端·算法·github·深度优先·动态规划·代理模式
H_BB2 天前
DFS实现回溯算法
数据结构·c++·算法·深度优先
xiaoye-duck3 天前
《算法题讲解指南:递归,搜索与回溯算法--综合练习》--14.找出所有子集的异或总和再求和,15.全排列Ⅱ,16.电话号码的字母组合,17.括号生成
c++·算法·深度优先·回溯