题目:
题目链接:
题目大意:
给一个双向图,以 1 号节点为根节点,在其他节点上竖立一个牌子,代表可以到达几号点,问最后是否
存在这样一棵树:满足所有点都可以到达 1 号点 -- 并且每个点到 1 号点的距离都是最短的。
侃侃:
先来看一下第二个样例:
6 9
3 4
6 1
2 4
5 3
4 6
1 5
6 2
4 5
5 6
我们发现如果要在每个节点的位置竖立一个牌子,那么一定是竖立它的父节点(因为我们最 后要想到达 根节点,必然是向上走的),所以我们只需要知道每个节点的父节点就可以啦,如果说某个节点没有父节点,那么这个图必然是不满足条件的(说明无法到达根节点)
做法:
因为要求每个节点的父节点是 who,所以需要用 BFS 进行层次遍历一下,通过上图我们看到 图中是
存在环的,用 DFS 的话并不能达到层次的效果(层次也就是我们所说的深度),接着最后遍历一下就可
以啦。
Code:
#include <set>
#include <map>
#include <queue>
#include <deque>
#include <stack>
#include <cstdio>
#include <string>
#include <cstring>
#include <iostream>
#include <algorithm>
#define x first
#define y second
using namespace std;
typedef long long LL;
typedef pair<int,int>PII;
const int maxn = 2e5 + 10;
int deep[maxn],fa[maxn];
int t,n,m;
vector<int>G[maxn];
void BFS(int root) {
queue<int>Q;
Q.push(root);
fa[root] = 1;
while(Q.size()) {
int top = Q.front();
Q.pop();
for(int i = 0; i < G[top].size(); i ++) {
int y = G[top][i];
// 一个节点只能有一个父亲
if(fa[y]) continue;
Q.push(y);
fa[y] = top;
}
}
return ;
}
int main(void) {
scanf("%d%d",&n,&m);
int u,v;
for(int i = 1; i <= m; i ++) {
scanf("%d%d",&u,&v);
G[u].push_back(v);
G[v].push_back(u);
}
BFS(1);
bool flag = true;
for(int i = 2; i <= n; i ++) {
// 如果说某个节点没有父亲,则不在树上,必然走不到 1
// 有可能是孤立的点
if(fa[i] == 0) {
flag = false;
break;
}
}
if(!flag) puts("No");
else {
puts("Yes");
for(int i = 2; i <= n; i ++) {
printf("%d\n",fa[i]);
}
}
return 0;
}