蓝桥杯-景区导游-DFS

文章描述了一个问题,关于在一个由N个景点组成、形成树状结构的景区中,资深导游小明需要调整游览线路,跳过一个景点,计算新的摆渡车时间。通过输入景点数量、摆渡车连接及原定路线,输出跳过每个景点后的总时间。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

某景区一共有 N 个景点,编号 1 到 N。景点之间共有 N − 1 条双向的摆渡车线路相连,形成一棵树状结构。在景点之间往返只能通过这些摆渡车进行,需要花费一定的时间。

小明是这个景区的资深导游,他每天都要按固定顺序带客人游览其中 K 个景点:A1, A2, . . . , AK。今天由于时间原因,小明决定跳过其中一个景点,只带游客按顺序游览其中 K − 1 个景点。具体来说,如果小明选择跳过 Ai,那么他会按顺序带游客游览 A1, A2, . . . , Ai−1, Ai+1, . . . , AK, (1 ≤ i ≤ K)。

请你对任意一个 Ai,计算如果跳过这个景点,小明需要花费多少时间在景点之间的摆渡车上?

输入格式

第一行包含 2 个整数 N 和 K。

以下 N − 1 行,每行包含 3 个整数 u, v 和 t,代表景点 u 和 v 之间有摆渡车线路,花费 t 个单位时间。

最后一行包含 K 个整数 A1, A2, . . . , AK 代表原定游览线路。

输出格式

输出 K 个整数,其中第 i 个代表跳过 Ai 之后,花费在摆渡车上的时间。

样例输入

复制

6 4
1 2 1
1 3 1
3 4 2
3 5 2
4 6 3
2 6 5 1

样例输出

复制

10 7 13 14

提示

原路线是 2 → 6 → 5 → 1。

当跳过 2 时,路线是 6 → 5 → 1,其中 6 → 5 花费时间 3 + 2 + 2 = 7,5 → 1 花费时间 2 + 1 = 3,总时间花费 10。

当跳过 6 时,路线是 2 → 5 → 1,其中 2 → 5 花费时间 1 + 1 + 2 = 4,5 → 1 花费时间 2 + 1 = 3,总时间花费 7。

当跳过 5 时,路线是 2 → 6 → 1,其中 2 → 6 花费时间 1 + 1 + 2 + 3 = 7,6 → 1 花费时间 3 + 2 + 1 = 6,总时间花费 13。

当跳过 1 时,路线时 2 → 6 → 5,其中 2 → 6 花费时间 1 + 1 + 2 + 3 = 7,6 → 5 花费时间 3 + 2 + 2 = 7,总时间花费 14。

对于 20% 的数据,2 ≤ K ≤ N ≤ 102。

对于 40% 的数据,2 ≤ K ≤ N ≤ 104。

对于 100% 的数据,2 ≤ K ≤ N ≤ 105,1 ≤ u, v, Ai ≤ N,1 ≤ t ≤ 105。保证Ai 两两不同。

#include <iostream>
#include<map>
#include<vector>
using namespace std;
#define INF 0x3f3f3f
#define int long long
#define deb(x)cout<<#x<<"="<<x<<'/n'
const int N = 2e5 + 10;
typedef pair<int, int>pii;
map<pii, int>st;               //key是起点和终点,value是距离
int a[N];                      //节点的顺序,即要游览的景点顺序

vector<pii>e[N];            //key是当前节点,value是终点和距离

bool dfs(int s,int u,int v,int father,int sum)
{
	if (u == v)
	{
		st[{v, s}]=st[{s, v}] = sum;
		return true;
	}
	for (int i = 0; i < e[u].size(); i++) //循环找到当前节点的没有经过的节点
	{
		int son = e[u][i].first;
		if ( son== father) continue;
		sum += e[u][i].second;
		if(dfs(s, son, v, u, sum))return true;
	}
	return false;
}

void solve()
{
	int n, k;
	cin >> n >> k;
	for (int i = 0; i < n-1; i++)
	{
		int x, y, t;
		cin >> x >> y >> t;
		e[x].push_back({ y,t });                    //输入一个游览图
		e[y].push_back({ x,t });
	}
	for (int i = 0; i < k; i++)
	{
		cin >> a[i];             //输入k个要又游览的景点
	}

	int ans = 0;                 //计算需要游览的景点的距离
	for (int i = 0; i < k; i++)
	{
		dfs(a[i], a[i], a[i + 1], -1, 0);
		ans += st[{a[i], a[i + 1]}];
	}
	for (int i = 0; i < k; i++)
	{
		int temp;
		if (i == 0)
		{
			temp = ans - st[{a[i], a[i + 1]}];
		}
		else if (i == k - 1)
		{
			temp = ans - st[{a[i-1], a[i]}];
		}
		else
		{		
			dfs(a[i - 1], a[i - 1], a[i + 1], -1, 0);
			temp = ans - st[{a[i], a[i + 1]}] - st[{a[i - 1], a[i]}] + st[{a[i - 1], a[i + 1]}];

		}
		cout << temp << endl;
	}
}
signed main()
{
	ios::sync_with_stdio;
	cin.tie(0);
	cout.tie(0);
	int num = 1;
	while (num--)
	{
		solve();
	}
}

### 蓝桥杯景区导游问题的Java实现 #### 问题分析 蓝桥杯中的“景区导游”问题是典型的图遍历问题,通常可以通过深度优先搜索(DFS)来解决。该类问题的核心在于构建一个表示景点之间连接关系的数据结构——邻接表或邻接矩阵,并通过递归的方式访问每一个节点[^1]。 以下是基于DFS算法的一个通用解决方案: --- #### Java代码实现 ```java import java.util.*; public class TourGuide { private static List<List<Integer>> adjacencyList; private static boolean[] visited; public static void main(String[] args) { Scanner scanner = new Scanner(System.in); int n = scanner.nextInt(); // 景点数量 int m = scanner.nextInt(); // 道路数量 // 初始化邻接表 adjacencyList = new ArrayList<>(); for (int i = 0; i <= n; i++) { adjacencyList.add(new ArrayList<>()); } // 构建邻接表 for (int i = 0; i < m; i++) { int u = scanner.nextInt(); int v = scanner.nextInt(); adjacencyList.get(u).add(v); adjacencyList.get(v).add(u); // 如果是无向图,则需要双向添加边 } // DFS初始化 visited = new boolean[n + 1]; dfs(1); // 假设从景点1出发 System.out.println("所有可到达的景点已游览完毕!"); } /** * 深度优先搜索函数 */ private static void dfs(int node) { visited[node] = true; System.out.print(node + " "); // 访问当前节点 for (Integer neighbor : adjacencyList.get(node)) { // 遍历邻居节点 if (!visited[neighbor]) { dfs(neighbor); // 对未访问过的邻居继续DFS } } } } ``` --- #### 关键点解析 上述代码实现了基本的DFS逻辑,适用于大多数类似的路径规划问题。具体说明如下: - **数据结构的选择** 使用`ArrayList<ArrayList<Integer>>`作为邻接表存储景点之间的连通性信息。这种方式相较于邻接矩阵更加节省空间,尤其当图较为稀疏时表现更优。 - **输入处理** 输入部分假设用户会提供两个整数`n`和`m`分别代表景点总数以及道路条数。随后按照每一对`(u, v)`的形式描述各条道路的信息。 - **DFS核心逻辑** `dfs()`方法采用递归形式完成对整个图的探索过程。每当进入一个新的节点时标记其状态为已访问(`true`)并打印出来;接着逐一尝试访问与其相连但尚未被触及的所有其他节点。 --- #### 进一步优化方向 尽管以上程序能够满足基础需求,但在实际竞赛场景下可能还需要考虑更多细节,比如: - 如何判断是否存在无法抵达的目标地点? - 当存在多个起点或者环状回路时应如何调整策略? 针对这些问题可以引入额外辅助变量记录相关信息以便后续统计计算得出最终结论。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值