解题思路:

要求两个点之间的最点距离,同时属于同一个洞窟的点他们之间的距离为0

那么该问题可以转换为求解两个洞窟的最短距离

依次构建的图是关于洞窟的而不是点

例如1 3 2 1 2 3:1和4点都属于1号洞窟那么他们两点邻接的其他点,也就等价于1号洞窟邻接了其他洞窟

从而构建洞窟的邻接表


然后通过bfs去求解两个洞窟之间的最小深度

bfs深度依次递增的,因此只要达到了终点洞窟此时的深度就是最小的深度

没必要再继续深度遍历

参考代码:

#include <bits/stdc++.h>
using namespace std;

int n,m;
vector<int> a;//a[i]表示i所属于的洞窟编号 
vector<int> b[5005];//存储洞窟之间的图 

//通过bfs得到两个洞窟之间最近的距离 
int solve(int x,int y){
	if(x == y) return 0;
	queue<int> q;
	q.push(x);
	vector<int> depth(5005,0);//记录该洞窟编号到x的深度,即距离 
	vector<int> vis(5005,0);//标记访问避免重复访问 
	vis[x] = 1;
	//bfs遍历 
	while(!q.empty()){
		int t = q.front();
		q.pop();
		for(int u : b[t]){
			if(u == y) {
				//达到目的点,直接返回,通过bfs遍历 深度是从小到大
				//因此第一次到达目的点就一定是最小的深度 
				return depth[t] + 1;
			}
			else {
				//已经入队了就跳过 
				if(vis[u]) continue;
				//入队 
				q.push(u);
				//标记入队 
				vis[u] = 1;
				//该点到x的深度是x到t的深度 + t到x深度(t是x的邻接点,故深度为1) 
				depth[u] = depth[t] + 1;
			}
		}
	}
}

int main() {
	cin>>n>>m;
	a.resize(n + 1,0);
	for(int i = 1;i <= n;i++){
		cin>>a[i];
	}
	for(int i = 0;i < n-1;i++){
		int x,y;
		cin>>x>>y;
		//构造的是洞窟图,例如1,3是1号洞窟,2,4,5是2号洞窟
		//那么就构造1号洞窟和2号洞窟的关系
		//1,3是1号洞窟,他们能到达的洞窟 合并起来就是1号洞窟能到达其他洞窟的情况 
		//这里还可以先进行去重处理,避免洞窟的邻接点有重复
		if(a[x] != a[y]){//同一个洞窟的没必要再加入图结构
			b[a[x]].push_back(a[y]);
			b[a[y]].push_back(a[x]);
		}
	}
	
	for(int i =0;i<m;i++){
		int x,y;
		cin>>x>>y;
		//输出所求 其实就是这两点所属洞窟的最小深度(距离) 
		cout<<solve(a[x],a[y])<<endl;
	}
    return 0;
}


点赞(0)
 

0.0分

0 人评分

C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:

一点编程也不会写的:零基础C语言学练课程

解决困扰你多年的C语言疑难杂症特性的C语言进阶课程

从零到写出一个爬虫的Python编程课程

只会语法写不出代码?手把手带你写100个编程真题的编程百练课程

信息学奥赛或C++选手的 必学C++课程

蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程

手把手讲解近五年真题的蓝桥杯辅导课程

评论列表 共有 0 条评论

暂无评论