pta 5-2 喊山 (30分)

5-2 喊山 (30分)

喊山,是人双手围在嘴边成喇叭状,对着远方高山发出“喂—喂喂—喂喂喂……”的呼唤。呼唤声通过空气的传递,回荡于深谷之间,传送到人们耳中,发出约定俗成的“讯号”,达到声讯传递交流的目的。原来它是彝族先民用来求援呼救的“讯号”,慢慢地人们在生活实践中发现了它的实用价值,便把它作为一种交流工具世代传袭使用。

一个山头呼喊的声音可以被临近的山头同时听到。题目假设每个山头最多有两个能听到它的临近山头。给定任意一个发出原始信号的山头,本题请你找出这个信号最远能传达到的地方。

输入格式:

输入第一行给出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

代码:

#include<bits/stdc++.h>
using namespace std;
vector<int> q[10005];//用vector数组代替邻接表
int vis[10005], n, flag, mi, mi1;
queue<int> p;
void bfs(int u)
{
    int i;
    p.push(u);//入队列
    vis[u] = 1;//标记已经用过,1代表第一个山头走了
    while(!p.empty())//不为空
    {
        u = p.front();//取队首值
        p.pop();//出队
        if(vis[u] >= mi)//至少得走过两个山头
        {
            if(vis[u] > mi)//更新mi, mi1
            {
                mi = vis[u];
                mi1 = u;
            }
            else
            {
                mi1 = min(u, mi1);//取最小编号的山头
            }
        }
        for(i = 0; i < q[u].size(); i++)
        {
            if(!vis[q[u][i]])//为0代表没有走过
            {
                p.push(q[u][i]);//入队列
                vis[q[u][i]] = vis[u] + 1;//更新vis值
            }
        }
    }
}
int main()
{
    int u, v, m, k;
    while(~scanf("%d %d %d", &n, &m, &k))
    {
        while(m--)
        {
            scanf("%d %d", &u, &v);
            q[u].push_back(v);//对应起始点的下标,存入目的地点
            q[v].push_back(u);
        }
        while(k--)
        {
            mi = 2;//走过山头数
            mi1 = 10005;//编号
            memset(vis, 0, sizeof(vis));//标记已经走过的山头同时判断已经走了多远
            scanf("%d", &u);
            bfs(u);
            if(mi1 == 10005) printf("0\n");//没有第二座山头可以走
            else printf("%d\n", mi1);
        }
    }
}
  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值