【无标题】

题目链接

题意:给出有n个节点n-1条边的树,然后给出n个节点中的m个节点,询问在另外n-m个节点中是否存在到m个节点距离都相等的节点

思路:多源bfs,将m个节点当作起点,对于每一给点记录一个到最近起点的距离,记录一个移动这些距离可以到达多少个起点,如果有一个节点的可达点数为m则说明这是一个合法节点

ac代码:

#include<bits/stdc++.h>
#define endl '\n'
#define ll long long
#define INF 0x3f3f3f3f
#define pb push_back
// #define int long long
#define Mirai ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
using namespace std;
typedef pair<int,int> pii;
const int N=2e5+10;
int n,m;
int dist[N];//记录某一点到距离最近的辅导班的距离
//定义某一点的最短距离为这个点到所有辅导班中距离最近的一个辅导班的距离
int num[N];//记录某一点移动最短距离可以到达的辅导班数量
//如果某一点的num值为m,则说明这一点到所有辅导班的距离都是相等的
//也就是存在合法结果
unordered_map<int,int> mp;//用于标记当前位置是辅导班
vector<int> g[N];
void solve()
{
    cin>>n;
    memset(dist,-1,sizeof dist);
    for(int i=0;i<n-1;i++)//有n个节点的树一共有n-1条边
    {
        int u,v;
        cin>>u>>v;
        g[u].pb(v);//无向边
        g[v].pb(u);
    }
    cin>>m;
    queue<int> q;
    for(int i=0;i<m;i++)
    {
        int x;
        cin>>x;
        mp[x]=1;
        dist[x]=0;//所有辅导班都为起始点,距离都为0
        num[x]++;//对于辅导班所在的节点一定是到当前节点的辅导班最近
        //并且没有相同距离的辅导班,所以辅导班所在节点的num值为1
        q.push(x);//将所有辅导班节点都加入队列中(多源bfs)
    }
    while(q.size())
    {
        int u=q.front();
        q.pop();
        for(auto v:g[u])
        {
            if(dist[v]==-1)//第一次遍历到某一点
            {
                num[v]=num[u];//这两点的num值应该是相同的
                dist[v]=dist[u]+1;//更新最短距离
                q.push(v);//只有需要更新临点距离的点才加入队列
            }
            else if(dist[v]==dist[u]+1)
            {
                num[v]+=num[u];
            }
        }
    }
    for(int i=1;i<=n;i++)
    {
        if(num[i]==m&&!mp.count(i))//如果当前节点的num值为辅导班数量并且当前节点不为辅导班
        //则为合法节点
        {
            // cout<<num[i]<<endl;
            cout<<"Yes"<<endl;
            return ;
        }
    }
    cout<<"No"<<endl;
}
signed main()
{
    Mirai;
    int T=1;
    //cin>>T;
    while(T--)
    {
        solve();
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值