Codeforces Round #756 (Div. 3) E1. Escape The Maze (easy version)

题目

1.题目大意

  • 有一个有 n 个结点的二叉树,小 V 位于根节点 1 ,其他人在其它结点,每人单独对应一个结点
  • 每人一次只能移动一步
  • 求:是否存在一个叶子结点,使小 V 可以最先到达该点

2.题目分析

  • 题目大意里已经抽象得差不多了,基本思路就是对每个点深搜,存在到根节点的路径是最短路径就成立。
  • 遍历每个无人的叶子结点时,先求出该点到根节点的最短路径(即从根节点开始遍历得到叶结点的深度),当有一个其他点到选中点的路径小于根节点到该点的路径时,该点就不成立直接跳过,节省时间。
  • 感觉广搜其实也可以,但是可能会 TLE 。
  • 上面的思路需要深搜的次数太多了,简化一下,一个数组存储叶节点的深度,一个数组存储叶节点到朋友的最短距离,再来一次深搜找出叶节点进行比较就结束了。

3.题目代码

#include <iostream>
#include <vector>
#include<bits/stdc++.h>
#define MAX 200005
using namespace std;

vector<int> e[MAX];
int dp[MAX];
int dis[MAX];
int n;
const int INF = 0x3f3f3f3f;

void dfs(int u, int pre)
{
    if(u!=1)
        dp[u] = dp[pre]+1;
    for(int v: e[u])
    {
        if(v==pre) continue;
        dfs(v, u);
    }
}

void dfs2(int u,int pre)
{
    if(dis[u] == 0) return;
    int t = INF;
    for(int v: e[u])
    {
        if(v==pre) continue;
        dfs2(v, u);
        t = min(t, dis[v]);
    }
    dis[u] = t+1;
}

bool dfs3(int u,int pre)
{
    if(dis[u]<=dp[u]) return 0;
    if(e[u].size()==1&&u!=1) return 1;
    bool f = 0;
    for(int v: e[u])
    {
        if(v==pre) continue;
        f |= dfs3(v, u);
    }
    return f;
}

int main()
{
    int t;
    cin >> t;
    //int n, k;
    int k;
    while(t--)
    {
        cin >> n >> k;
        //memset(f,0,sizeof(f));
        for(int i=1;i<=n;i++)
        {
            e[i].clear();
            dis[i] = INF;
            dp[i] = 0;
        }
        int tmp;
        for(int i=1;i<=k;i++)
            cin >> tmp, dis[tmp] = 0;
        int u, v;
        for(int i=1;i<n;i++)
        {
            cin >> u >> v;
            e[u].push_back(v);
            e[v].push_back(u);
        }
        dfs(1,0);
        dfs2(1,0);
        if(dfs3(1,0))
            cout << "YES" << endl;
        else
            cout << "NO" << endl;
    }
    return 0;
}
posted @ 2022-01-10 00:17  仪战群儒  阅读(96)  评论(0编辑  收藏  举报