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 是不支持的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章