CF1611E1 主人与朋友(简单)

CF1611E1 Escape The Maze (easy version) - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

思维+图论

题意就是给你一棵双向无权的树,给你几个点,这几个点和1号点开始的同时出发,速度一样,然后能不被碰到走到叶子点就输出yes,否则输出no

无权(边权是1)多个点自然想到多源bfs,但是一味的用多源bfs,1号点没办法,不能搅和在里面,也算不出来

其实一个题目告诉你了,最重要的是发现本质,算法的框架,而不是一味的按照题目去钻牛角尖

这里就是看1号点走到叶节点会不会中途和其他点碰到

那就是枚举所有的点,如果是叶节点(连边只有1条),并且1号点到这个点的最短距离<朋友们到这个点的最小距离就可以,否则no

为什么呢

我刚开始想的时候漏掉了一个条件(这些路都是连通的),尤其是两种人都能走到的点,路径都是相通的,然后速度也一样

从根节点到叶节点的路径只有一条,如果这个路径上有一个点是主人的距离>=朋友的距离,那朋友一定会沿着路径去追到主人(这条路径,这个叶结点就算作废)

而且bfs啊,它是一圈一圈往外扩展的,所以到叶节点的距离必定大于等于主人

所以如果主人到叶节点的距离<朋友的距离,那这个路径上所有的点都是小于的,必然不会碰到

所以答案就是看看刚刚的条件(那就是枚举所有的点,如果是叶节点(连边只有1条),并且1号点到这个点的最短距离<朋友们到这个点的最小距离就可以,否则no)是否满足,满足就yes,不满足就no

 

 

复制代码
#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
const int N=2e5+10,M=1e6+10;
int h[N],e[M],ne[M],idx,d[N],co[N],dist[N];
bool st[N];
queue<int> q;
queue<int> qu;
void add(int a,int b)
{
    e[idx]=b;
    ne[idx]=h[a];
    h[a]=idx++;
}
void bfs1()//1号点为起点 
{
    qu.push(1);
    dist[1]=1;
    while(qu.size())
    {
        auto t=qu.front();
        qu.pop();
        for(int i=h[t];i!=-1;i=ne[i])
        {
            int j=e[i];
            if(dist[j]==-1)
            {
                dist[j]=dist[t]+1;
                qu.push(j);
            }
        }
    }
}
void bfs2()//多源 
{
    while(q.size())
    {
        auto t=q.front();
        q.pop();
        for(int i=h[t];i!=-1;i=ne[i])
        {
            int j=e[i];
            if(d[j]==-1)
            {
                d[j]=d[t]+1;
                q.push(j);
            }
        }
    }
}
int main(){
    int T;
    scanf("%d",&T);
    while(T--)
    {
        memset(co,0,sizeof(co));
        memset(dist,-1,sizeof(dist));
        memset(d,-1,sizeof(d));
        memset(h,-1,sizeof(h));
        int n,k;
        scanf("%d%d",&n,&k);
        for(int i=1;i<=k;i++)
        {
            int x;
            cin>>x;
            st[x]=true;
            q.push(x);
            d[x]=1;
        }
        for(int i=1;i<=n-1;i++)
        {
            int a,b;
            scanf("%d%d",&a,&b);
            add(a,b);
            add(b,a);
            co[a]++;
            co[b]++;
        }
        bfs1();//求1号点到每个叶子点的距离
        bfs2();//多源bfs
        int f=0;
        for(int i=2;i<=n;i++)
        {
            //cout<<co[i]<<" "<<dist[i]<<" "<<d[i]<<endl;
            if(co[i]==1&&dist[i]<d[i])
            {
                f=1;
                break;
            }
        }
        if(!f) cout<<"NO"<<endl;
        else cout<<"YES"<<endl;
    }
    return 0;
}
/*
连通是很重要的,因为一个点朋友能走,主人能走,那他们之间的路径都是相通的
满足主人从1号点到叶子点的距离等于朋友到这个叶子点的距离都小就可以了 


*/
复制代码

 

posted @   小志61314  阅读(23)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示