题目链接
题意:
给你一棵树,n个点,n-1条边
1、必须是1开始
2、判断是否为合法的BFS序列
小结:
一开始,我认为可以把这棵树,以某一点为根节点,然后历遍下去,求出对应节点的层数,然后求一个前缀和。
判断前缀和是否相同。后来发现我错了,错就错在,不知道同一层可能是不同的子树混进来,那么就不是合法的BFS序列。
然后听取了胜营大佬的解法,豁然开朗,主要是因为,其实就是一个模拟。合法地模拟即可。
题解:
以下提供三种写法,其实三种写法都是异曲同工,但是有一点不同的是运来兄的做法,建图更简单,而且非常巧妙,只要不是当前节点的子节点,那么就不标记,只要最后检查一下是否有节点没有被标记上,那么就可以判断是否合法的BFS序列。
然后我的做法其实是窃取胜营兄的做法,就是一个简单的模拟,首先判断这个节点的子节点有多少个,并且标记上,然后看看给定的序列接下来的k个是为刚才标记上的节点。
其实做法都一样,但是写法上,我还是参考别人的写了一遍,因为多写才有收获。
我的写法:
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+100;
typedef pair<int,int> P;
typedef long long ll;
int head[N],cnt,dis[N],a[N],vis[N];
ll sum[N],Sum=0;
typedef struct Node{
int to,next;
Node (int To=0,int Nt=-1):
to(To),next(Nt){}
}Edge;
Edge e[N<<1];
void init(){
memset(head,-1,sizeof(head));
cnt=0;
}
void add_edge(int u,int v){
e[cnt]=Node(v,head[u]);
head[u]=cnt++;
}
int main()
{
init();
int n,u,v;
scanf("%d",&n);
for(int i=1;i<n;i++){
scanf("%d%d",&u,&v);
add_edge(u,v);
add_edge(v,u);
}
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
/*for(int u=1;u<=n;u++){
printf("%d : ",u);
for(int i=head[u];~i;i=e[i].next){
printf("%d ",e[i].to);
}puts("");
}*/
queue< int >Q;
Q.push(a[1]);
vis[a[1]]=1;
int cur=2,flag=1;
if(a[1]!=1){
flag=0;
}
while(!Q.empty()){
int t=Q.front();
Q.pop();
int cnt=0;
for(int i=head[t];~i;i=e[i].next){
int to=e[i].to;
if(!vis[to]){
vis[to]=1;
cnt++;
}
}
if(cnt==0){
continue;
}
//printf("t : %d\n",t);
//printf("a[%d]=%d, cnt = %d ,flag = %d \n",cur,a[cur],cnt,flag);
int D=cur+cnt;
//printf("D: %d\n",D);
for(int i=cur;i<D;i++){
if(vis[a[i]]==0){
flag=0;
break;
}else{
Q.push(a[i]);
//printf("%d\n",a[i]);
}
}
cur=D;
}
puts(flag?"Yes":"No");
return 0;
}
胜营兄的写法:
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+100;
typedef pair<int,int> P;
typedef long long ll;
int head[N],cnt,dis[N],a[N],vis[N];
ll sum[N],Sum=0;
typedef struct Node{
int to,next;
Node (int To=0,int Nt=-1):
to(To),next(Nt){}
}Edge;
Edge e[N<<1];
void init(){
memset(head,-1,sizeof(head));
cnt=0;
}
void add_edge(int u,int v){
e[cnt]=Node(v,head[u]);
head[u]=cnt++;
}
int main()
{
init();
int n,u,v;
scanf("%d",&n);
for(int i=1;i<n;i++){
scanf("%d%d",&u,&v);
add_edge(u,v);
add_edge(v,u);
}
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
int cur=2,flag=a[1]==1;
queue< int >Q;
Q.push(1);
vis[a[1]]=1;
while(!Q.empty()&&flag){
int u=Q.front();
Q.pop();
vector<int>V;
for(int i=head[u];~i;i=e[i].next)
if(!vis[e[i].to])
V.push_back(e[i].to),vis[e[i].to]=1;
int k=V.size();
for(int i=0;i<k;i++)
flag&=vis[a[cur+i]],
Q.push(a[cur+i]);
cur+=k;
}
puts(flag?"Yes":"No");
return 0;
}
运来兄的写法:
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+100;
typedef pair<int,int> P;
typedef long long ll;
int a[N],vis[N];
map<int,int>V[N];
int main()
{
int n,u,v;
scanf("%d",&n);
for(int i=1;i<n;i++){
scanf("%d%d",&u,&v);
//add_edge(u,v);add_edge(v,u);
V[u][v]=1;
V[v][u]=1;
}
for(int i=1;i<=n;i++){ scanf("%d",&a[i]); }
if(a[1]!=1) return puts("NO")*0;
int now=2;
queue<int>Q;
Q.push(1);
while(!Q.empty()){
int u=Q.front();
Q.pop();vis[u]=1;
while(now<=n&&V[u].find(a[now])!=V[u].end()){
Q.push(a[now++]);
}
}
int flag=1;
for(int i=1;i<=n;i++){
flag&=vis[i];
}
return 0*puts(flag?"Yes":"No");
}