A30335. 小杨寻宝
填空题
困难
知识点
题目描述
小杨寻宝
题目描述
小杨有一棵包含 n 个节点的树,树上的一些节点放置有宝物。
小杨可以任意选择一个节点作为起点并在树上移动,但是小杨只能经过每条边至多一次,当小杨经过一条边后,这条边就会消失。小杨每经过一个放置有宝物的节点就会取得该宝物。
小杨想请你帮他判断自己能否成功取得所有宝物。
输入格式
第一行包含一个正整数 t,代表测试用例组数。
接下来是t组测试用例。对于每组测试用例,一共n+1行。
第一行包含一个正整数 n,代表树的节点数。
第二行包含n个非负整数 a1,a2,,,,an,其中如果 ai =1,则节点 放置有宝物,若 ,ai =0,则节点 i 没有宝物。
之后 n-1 行,每行包含两个正整数 xi ,yi ,代表存在一条连接节点 xi 和 yi 的边。
输出格式
对于每组测试数据,如果小杨能成功取得所有宝物,输出 Yes,否则输出 No。
输入样例
2
5
0 1 0 1 0
1 2
1 3
3 4
3 5
5
1 1 1 1 1
1 2
1 3
3 4
3 5输出样例
Yes
No
参考答案
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5+10;
vector<int> g[N];
int col[N],dep[N],has[N];
void dfs(int x,int fa) {
dep[x]=dep[fa]+1;
for (auto i:g[x]) {
if(i!=fa) {
dfs(i,x);
}
}
}
bool dfs2(int x,int fa) {
for (auto i:g[x]) {
if(i!=fa) {
auto res = dfs2(i,x);
if(res==false)return false;
if(has[i]||col[i])has[x]++;
}
}
if(has[x]>1)return false;
return true;
}
int main() {
int t;
cin>>t;
while(t--) {
int n;
cin>>n;
for (int i=1;i<=n;i++) {
dep[i]=0;
g[i].clear();
cin>>col[i];
}
for (int i=1;i<n;i++) {
int u,v;
cin>>u>>v;
g[u].push_back(v);
g[v].push_back(u);
}
dfs(1,0);
int mx=0,pos=0;
for (int i=1;i<=n;i++) {
has[i]=0;
if(col[i]) {
if(dep[i]>mx) {
mx=dep[i];
pos=i;
}
}
}
bool res= dfs2(pos,0);
if(res)cout<<"Yes\n"; else cout<<"No\n";
}
}
上一题
下一题