D. Valid BFS?(依照点出现的顺序对存的边进行排序)

Problem - D - Codeforces

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(); 
	}
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值