欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

PTA:7-102 喊山 (30分)---解析(bfs广度优先搜索,vector)

程序员文章站 2022-06-08 08:11:00
...

7-102 喊山 (30分)

喊山,是人双手围在嘴边成喇叭状,对着远方高山发出“喂—喂喂—喂喂喂……”的呼唤。呼唤声通过空气的传递,回荡于深谷之间,传送到人们耳中,发出约定俗成的“讯号”,达到声讯传递交流的目的。原来它是彝族先民用来求援呼救的“讯号”,慢慢地人们在生活实践中发现了它的实用价值,便把它作为一种交流工具世代传袭使用。(图文摘自:http://news.xrxxw.com/newsshow-8018.html)
PTA:7-102 喊山 (30分)---解析(bfs广度优先搜索,vector)
一个山头呼喊的声音可以被临近的山头同时听到。题目假设每个山头最多有两个能听到它的临近山头。给定任意一个发出原始信号的山头,本题请你找出这个信号最远能传达到的地方。

输入格式:
输入第一行给出3个正整数n、m和k,其中n(≤10000)是总的山头数(于是假设每个山头从1到n编号)。接下来的m行,每行给出2个不超过n的正整数,数字间用空格分开,分别代表可以听到彼此的两个山头的编号。这里保证每一对山头只被输入一次,不会有重复的关系输入。最后一行给出k(≤10)个不超过n的正整数,数字间用空格分开,代表需要查询的山头的编号。

输出格式:
依次对于输入中的每个被查询的山头,在一行中输出其发出的呼喊能够连锁传达到的最远的那个山头。注意:被输出的首先必须是被查询的个山头能连锁传到的。若这样的山头不只一个,则输出编号最小的那个。若此山头的呼喊无法传到任何其他山头,则输出0。

输入样例:
7 5 4
1 2
2 3
3 1
4 5
5 6
1 4 5 7

输出样例:
2
6
4
0

思路
开始也想到过并查集和dfs,这两种方法最后都没想出结果,最后用来bfs广度优先搜索。
下面介绍一下本题的bfs解题思路:
用搜索方法时,首先要知道用什么来存储树,在这里用的动态数组vector,这很关键(我开始就用的二ou维数组,最后就超时了)。
接着就是输入数据,常规的树的遍历了。我这里定义了一个数组d[]来保存每个节点的深度,就是通过这个来求解出最远的节点。
需要注意的是: 样例中有重复的点,比如1->2->3和1->3,这里的3相当于遍历了两次,不注意的话可能还会输出最远的山头是3呢;所以我做的处理是,在遍历树时,加入了一个判断,即 if(!vis[r[t][i]]&&!d[r[t][i]]),这里的!d[r[t][i]]防止了这种情况。因为在搜索离1最远的山头,肯定是以1为根节点遍历树,首先会遍历其孩子节点2,3可以得到d[2],d[3]均为1了。这样当再遍历到2的孩子节点3时,就不会再计算了,直接不满足if条件跳过了。
有疑问的话,欢迎大家留言,我们继续讨论,嘻嘻!

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

int vis[10010],d[10010],n,m,k,kk,t;  //vis[]表示节点是否出现过,d[]表示当前节点的深度 
vector<int> r[10010]; //保存各个以r[i]为根结点的树 
queue<int> qu;

void bfs(){
	while(!qu.empty()){   //此循环为树的bfs 
		t = qu.front();
		qu.pop();
		vis[t] = 1;
		for(int i=0; i<r[t].size(); i++){
			if(!vis[r[t][i]]&&!d[r[t][i]]){  //如果该节点没被访问过,而且其深度没被计算过 
				qu.push(r[t][i]);
				d[r[t][i]]=d[t]+1;
			}
		}
	}
	//根据d[i]找出最远的节点 
	int maxx=-1;	
	for(int i=0; i<=n; i++){
		if(d[i]>maxx) maxx=d[i];
	}
	for(int i=0; i<=n; i++){
		if(d[i]==maxx){
			cout << i << endl;
			break;
		}
	}
	return;
} 

int main(){
	ios::sync_with_stdio(false);  //加快输入速度 
	int a,b;
	cin >> n >> m >> k;
	while(m--){
		cin >> a >> b;
		r[a].push_back(b);
		r[b].push_back(a);
	}
	while(k--){
		cin >> kk;
		memset(vis, 0, sizeof(vis));
		memset(d, 0, sizeof(d));
		qu.push(kk);  //树的根节点 
		bfs();
	}
	return 0;
}

PTA:7-102 喊山 (30分)---解析(bfs广度优先搜索,vector)
欢迎大家批评改正!!!