【模拟】Valid BFS?

12 篇文章 0 订阅
10 篇文章 0 订阅

题目链接

题意:

给你一棵树,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");
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值