喊山,是人双手围在嘴边成喇叭状,对着远方高山发出“喂—喂喂—喂喂喂……”的呼唤。呼唤声通过空气的传递,回荡于深谷之间,传送到人们耳中,发出约定俗成的“讯号”,达到声讯传递交流的目的。原来它是彝族先民用来求援呼救的“讯号”,慢慢地人们在生活实践中发现了它的实用价值,便把它作为一种交流工具世代传袭使用。(图文摘自:http://news.xrxxw.com/newsshow-8018.html)
一个山头呼喊的声音可以被临近的山头同时听到。题目假设每个山头最多有两个能听到它的临近山头。给定任意一个发出原始信号的山头,本题请你找出这个信号最远能传达到的地方。
输入格式:
输入第一行给出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
解题思路:思考问题,发现该问题是符合给出一个点 然后找到它联系的另一个点 继续往下找,符合按层遍历的特点。符合bfs的特点,思考用bfs解决问题。
using namespace std;
const int MAXN=10005;
vector<int>adj[MAXN]; //绘制图 因为每一对山头只输入一次 所以可用数组下标和元素这样的建立关系(值得学习的地方1)
bool visited[MAXN];
int dist[MAXN];
int bfs(int n){ //输入的这个数 以这个数为开头 开始遍历
memset(visited,false,sizeof(visited));
memset(dist,0,sizeof(dist));
queue<int>q;
q.push(n); //入队
visited[n]=true; //标记
int maxdist=0; //题目要求找最远的 故要用打擂台比较
int result=0; //最后输出的山头编号
while(!q.empty()){
int current=q.front();
q.pop(); //出队(队首元素)开始遍历访问
//遍历元素的套路 就是有没有访问过 然后根据题目入不入队 做什么判断
for(int ne:adj[current]) {//找这个点的邻居 建立遍历器ne
if(!visited[ne]){
visited[ne]=true;
dist[ne]=dist[current]+1;
if(dist[ne]>maxdist){
maxdist=dist[ne];
result=ne; //更新最远山头的位置
}
else if(dist[ne]==maxdist){
result=min(ne,result);
}
q.push(ne); //将此邻居(关联点)入队;
}
}
}if(maxdist==0)
return 0;
return result;
}
int main(){
int n,m,k;
cin>>n>>m>>k;
for(int i=0;i<m;i++){
int u,v;
cin>>u>>v;
adj[u].push_back(v);
adj[v].push_back(u);
}
while(k--){
int num;
cin>>num;
cout<<bfs(num)<<"\n";
}
return 0;
}`
``
反思:技巧1.根据一对山头不重复输入的特性 利用数组下标和元素一一对应
2.bfs的基本思路:
思考准备需要的数据
将起始节点放入队列
将起始节点标记为已访问
当队列不为空时,循环执行以下操作:
将队头节点弹出,访问该节点,将与该节点相邻的且未访问的节点入队(并根据题目要求进行相应的对应措施),并标记为已访问;
搜索完毕
通常可用于解决图的遍历,最短路问题,联通块问题等
标签:练习题,dist,山头,int,ne,喊山,bfs,visited
From: https://www.cnblogs.com/yue-mikasa/p/18675670