AtCoder题解——Beginner Contest 168——D - .. (Double Dots)

题目相关

题目链接

AtCoder Beginner Contest 168 D题,https://atcoder.jp/contests/abc168/tasks/abc168_d

Problem Statement

There is a cave.

The cave has N rooms and M passages. The rooms are numbered 1 to N, and the passages are numbered 1 to M. Passage ii connects Room Ai and Room Bi bidirectionally. One can travel between any two rooms by traversing passages. Room 1 is a special room with an entrance from the outside.

It is dark in the cave, so we have decided to place a signpost in each room except Room 1. The signpost in each room will point to one of the rooms directly connected to that room with a passage.

Since it is dangerous in the cave, our objective is to satisfy the condition below for each room except Room 1.

  • If you start in that room and repeatedly move to the room indicated by the signpost in the room you are in, you will reach Room 11 after traversing the minimum number of passages possible.

Determine whether there is a way to place signposts satisfying our objective, and print one such way if it exists.

Input

Input is given from Standard Input in the following format:

N M
A1 B1
:
AM BM

Output

If there is no way to place signposts satisfying the objective, print No.

Otherwise, print N lines. The first line should contain Yes, and the i-th line (2 ≤ i ≤ N) should contain the integer representing the room indicated by the signpost in Room i.

Samples1

Sample Input 1

4 4
1 2
2 3
3 4
4 2

Sample Output 1

Yes
1
2
2

Explaination

If we place the signposts as described in the sample output, the following happens:

  • Starting in Room 2, you will reach Room 1 after traversing one passage: (2)→1. This is the minimum number of passages possible.
  • Starting in Room 3, you will reach Room 1 after traversing two passages: (3)→2→1. This is the minimum number of passages possible.
  • Starting in Room 4, you will reach Room 1 after traversing two passages: (4)→2→1. This is the minimum number of passages possible.

Thus, the objective is satisfied.

Samples2

Sample Input 2

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

Sample Output 2

Yes
6
5
5
1
1

If there are multiple solutions, any of them will be accepted.

Constraints

  • All values in input are integers.
  • 2 ≤ N ≤ 10^5
  • 1 ≤ M ≤ 2×10^5
  • 1 ≤ Ai, Bi ≤ N (1 ≤ i ≤ M )
  • Ai ≠ Bi (1 ≤ i ≤ M)
  • One can travel between any two rooms by traversing passages.

题解报告

本题含义

山洞里有 N 个房间,有 M 个通道。房间编号从 1 到 N,通道编号从 1 到M。通道 i 双向连接房间 Ai 通向 Bi。1 号房是总出入口。我们需要在每个房间(除了第 1 个房间)放置一个路标,该路标指明通过通道连接到另外一个房间号码。问我们是否存在解决方案。

其实到了这里,我们应该比较明确这是一个搜索问题,也就是最短路径问题,那么经验告诉我们,最好的方法是 BFS。本题不能使用 DFS,因为有可能会出现环。有人要问为什么啊?没什么内核,就是题目做多了,看到题目的意思就知道可能的方法。如下面马上要分析的样例数据1,我们可以看到一个环,因此使用 DFS 是不适合的。而且,我们看到原题中出现 minimum 的字样,就是说最短路径嘛,哪肯定是 BFS。

样例数据分析

样例数据1

有 4 个房间,4 个通道。第 1 号通道连接房间 1 和 2;第 2 号通道连接房间 2 和 3;第 3 号通道连接房间 3 和 4;第 4 号通道连接房间 4 和 2。这样我们可以绘制出如下的图。

下面我们从第 2 号房间开始,逐一遍历。

2 号房间要到 1号房间。我们可以看出最短的路径应该是 2->1,,因此我们只需要在 2 号房间的路标上写上 1 即可。

3 号房间要到 1号房间。我们可以看出最短的路径应该是 3->2->1,这样我们只需要在 3 号房间的路标上写上 2 即可。

4 号房间要到 1号房间。我们可以看出最短的路径应该是 4->2->1,这样我们只需要在 4 号房间的路标上写上 2 即可。

样例数据2

有 6 个房间,9 个通道。第 1 号通道连接房间 3 和 4;第 2 号通道连接房间 6 和 1;第 3 号通道连接房间 2 和 4;第 4 号通道连接房间 5 和 3;第 5 号通道连接房间 4 和 6;第 6 号通道连接房间 1 和 5;第 7 号通道连接房间 6 和 2;第 8 号通道连接房间 4 和 5;第 9 号通道连接房间 5 和 9。这样我们可以绘制出如下的图。

下面我们从第 2 号房间开始,逐一遍历。

2 号房间要到 1号房间。我们可以看出最短的路径应该是 2->6->1,因此我们只需要在 2 号房间的路标上写上 6 即可。

3 号房间要到 1号房间。我们可以看出最短的路径应该是 3->5->1,这样我们只需要在 3 号房间的路标上写上 5 即可。

4 号房间要到 1号房间。我们可以看出最短的路径应该是 4->5->1 或者 4->6->1,这样我们只需要在 4 号房间的路标上写上 5 或者 6 即可。

5 号房间要到 1号房间。我们可以看出最短的路径应该是 5->1,这样我们只需要在 5 号房间的路标上写上 1 即可。

6 号房间要到 1号房间。我们可以看出最短的路径应该是 6->1,这样我们只需要在 6 号房间的路标上写上 1 即可。

数据范围分析

N 的最大值是 1e5。

M 的最大值是 2e5。

Ai 和 Bi 的最大值不会超过 N。

所以本题需要定义一个 2e5 大小的数组,数据类型使用 int 足够。

算法设计

没什么特殊的地方,直接套用 BFS 模板即可。核心就是从第 1 号房间出发,看一下能走到哪些房间,并记录下相连房间的连接记录。BFS 遍历完成后,从 2 号房间开始查看是否所有的房间都有连接性。

AC 参考代码

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 2e5+10;
vector<int> datas[MAXN];//通道关系
int ans[MAXN];//保存最近的房间号

void bfs() {
    queue<int> q;
    q.push(1);
    ans[1] = 1;

    while (!q.empty()) {
        int u = q.front();
        q.pop();

        for (auto v:datas[u]) {
            if (0==ans[v]) {
                q.push(v);
                ans[v] = u;
            }
        }
    }
}

int main() {
    int n,m;
    scanf("%d%d", &n, &m);
    for (int i=0; i<m; i++) {
        int u, v;
        scanf("%d%d", &u, &v);
        datas[u].push_back(v);
        datas[v].push_back(u);
    }

    bfs();

    //查询
    for (int i=2; i<=n; i++) {
        if (0==ans[i]) {
            printf("No\n");
            return 0;
        }
    }
    printf("Yes\n");
    for (int i=2; i<=n; i++) {
        printf("%d\n", ans[i]);
    }

    return 0;
}

P.S.

这里使用了 auto 变量,这个在 NOIP 是不支持的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

努力的老周

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值