题目
- 原题地址:E1. Escape The Maze (easy version)
- 题目编号:1611E1
- 目标算法:深搜(dfs)、最短路
- 难度评分:1700
1.题目大意
- 有一个有 n 个结点的二叉树,小 V 位于根节点 1 ,其他人在其它结点,每人单独对应一个结点
- 每人一次只能移动一步
- 求:是否存在一个叶子结点,使小 V 可以最先到达该点
2.题目分析
- 题目大意里已经抽象得差不多了,基本思路就是对每个点深搜,存在到根节点的路径是最短路径就成立。
遍历每个无人的叶子结点时,先求出该点到根节点的最短路径(即从根节点开始遍历得到叶结点的深度),当有一个其他点到选中点的路径小于根节点到该点的路径时,该点就不成立直接跳过,节省时间。
感觉广搜其实也可以,但是可能会 TLE 。
- 上面的思路需要深搜的次数太多了,简化一下,一个数组存储叶节点的深度,一个数组存储叶节点到朋友的最短距离,再来一次深搜找出叶节点进行比较就结束了。
3.题目代码
#include
#include
#include
#define MAX 200005
using namespace std;
vector 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> 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;
}