BFS算法定义如下:
考虑一个有n个编号为1到n的顶点的无向图。将q初始化为只包含顶点1的新队列,标记顶点1为已使用。
从队列q的头部提取一个顶点v。
打印顶点v的索引。
以任意顺序迭代所有这样的顶点u,使得u是v的邻居且尚未标记为已使用。标记顶点u为已使用,并将其插入队列q的尾部。
如果队列不为空,则继续从步骤2。
否则完成。
由于选择每个顶点的邻居的顺序可能会有所不同,因此BFS可以打印多个序列。
在这个问题中,您需要检查给定序列是否对应于从顶点1开始的给定树的一些有效BFS遍历。该树是一个无向图,每两个顶点之间恰好存在一条简单路径。
输入
第一行包含一个整数n(1≤n≤2⋅10^5),表示树中节点的数量。
接下来的n-1行描述了树的边。其中每行包含两个整数x和y(1≤x,y≤n)——树的相应边的端点。保证给定的图是一棵树。
最后一行包含n个不同的整数a1、a2、…、an(1≤ai≤n)——要检查的序列。
输出
如果序列对应于给定树的某个有效BFS遍历,则打印“Yes”(带引号以示清晰),否则打印“No”(带引号以示清晰)。
您可以以任何大小写打印每个字母。
Examples
Input
Copy
4 1 2 1 3 2 4 1 2 3 4
Output
Copy
Yes
Input
Copy
4 1 2 1 3 2 4 1 2 4 3
Output
Copy
No
两个测试样例中都有相同的树。
在这棵树中,有两种有效的 BFS(广度优先搜索)遍历顺序:
1,2,3,4
1,3,2,4
顺序 1,2,4,3 不对应任何有效的 BFS 遍历顺序。
题解:
既然题目以及给了我们点出现的顺序,那我们可以把vector存起来的边按照,点出现的顺序进行排序,这样存入队列的顺序,也会是按照点出现顺序进行排列的,这样只要看从队列取出来的点是否符合所给顺序即可
#include <cstdio>
#include <cstring>
#include <algorithm>
#include<iostream>
#include<vector>
#include<set>
#include<map>
#include<cmath>
#include<queue>
using namespace std;
typedef long long ll;
#define int long long
typedef pair<int,int> PII;
typedef unsigned long long ULL;
const int N = 3e5 + 10;
int mod = 1e9 + 7;
vector<int> p[N];
int vis[N];
int a[N];
int id[N];
int cmp(int x,int y)
{
return id[x] < id[y];
}
void solve()
{
int n;
cin >> n;
for(int i = 1;i < n;i++)
{
int x,y;
cin >> x >> y;
p[x].push_back(y);
p[y].push_back(x);
}
for(int i = 1;i <= n;i++)
{
cin >> a[i];
id[a[i]] = i;
}
for(int i = 1;i <= n;i++)
{
sort(p[i].begin(),p[i].end(),cmp);
}
queue<int> q;
q.push(1);
vis[1] = 1;
int l = 1;
while(q.size())
{
int t = q.front();
q.pop();
if(t != a[l])
{
cout <<"No";
return ;
}
l++;
for(auto ne:p[t])
{
if(!vis[ne])
{
vis[ne] = 1;
q.push(ne);
}
}
}
cout <<"Yes";
}
signed main()
{
ios::sync_with_stdio(0 );
cin.tie(0);cout.tie(0);
int t = 1;
// cin >> t;
while(t--)
{
solve();
}
}