P11249 [GESP202409 七级] 小杨寻宝

题目

传送门

思路

借鉴了这道题洛谷题解区的第一篇题解

如何判断能否成功取得所有宝物?

我们观察样例的第二个测试数据,我们可以发现只要一个结点(不包括自身),周围如果有3个为1的结点,那么这个小杨一定不能取得宝物,我们把这个点叫做donk点(不幸点有点怪怪的QWQ)

如何找到donk点?

以x点为根,如果他的子树有3个包括为1的结点,那么我们就一定不能到达

But

我们以x为根节点,那么它上面的结点如何查找,我们可以判断以x为根节点的子树是否有全部的为1的结点,如果有,我们就按上面做就好了,如果没有,x的父亲结点发现一定有一个为1的结点,这是我们的条件变为了判断如果他的子树有2个为1的结点,那么我们就不能到达!

综上所述

如果我们以x为根节点的树的为1的结点的数量如果不等于我们全部为1的结点的数量,那么我们就判断它是否子树有3个包括为1的结点,否则就判断他的子树是否有2个为1的结点,只要满足任意一个,我们就一定不能到达!!!

代码

有注释

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int n,m;
bool f=0;
int a[N];
vector<int>v[N]; 
int dfs(int x,int fa){//目前结点和他的父节点 
	if(f==1)return 0; 
	if(v[x].size()==1&&fa==v[x][0]){//叶子结点直接返回 
		return a[x];
	}
	int ans1=0,ans2=0;//ans1是有1的子树数量,ans2是子树为1结点的总数量 
	for(int i=0;i<v[x].size();i++){
		int u=v[x][i];
		if(u!=fa){//不是父节点 
			int s=dfs(u,x);
			if(f==1)return 0;//剪枝 
			if(s)ans1++;//如果有1 
			ans2+=s; 
		} 
	}
	if(f==1)return 0;
	ans2+=a[x];
	if((ans2!=m&&ans1>=2)||ans1>=3){//看我的综上所述 
		f=1;//发现donk点 
		return 0;
	}
	return ans2;//返回子树包含的1的数量 
} 
int main(){
	std::ios::sync_with_stdio(false);//关闭输入输出流 
	std::cin.tie(0);
	std::cout.tie(0); 
	int t;
	cin>>t;
	while(t--){
		cin>>n;
		f=0;//初始化 
		m=0;//初始化 
		for(int i=1;i<=n;i++){
			cin>>a[i];
			m+=a[i];//求全部为一结点的数量 
			v[i].clear();//初始化 
		}
		for(int i=1;i<n;i++){
			int x,y;
			cin>>x>>y;
			v[x].push_back(y);
			v[y].push_back(x);
		}
		dfs(1,0);//树的根节点可以随便取一个 
		if(!f){//如果没有donk点 
			cout<<"Yes";
		}
		else{//有donk点 
			cout<<"No";
		}
		cout<<'\n';
	}
	return 0;
} 

无注释

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int n,m;
bool f=0;
int a[N];
vector<int>v[N]; 
int dfs(int x,int fa){
	if(f==1)return 0; 
	if(v[x].size()==1&&fa==v[x][0]){
		return a[x];
	}
	int ans1=0,ans2=0;
	for(int i=0;i<v[x].size();i++){
		int u=v[x][i];
		if(u!=fa){
			int s=dfs(u,x);
			if(f==1)return 0;
			if(s)ans1++;
			ans2+=s;
		} 
	}
	if(f==1)return 0;
	ans2+=a[x];
	if((ans2!=m&&ans1>=2)||ans1>=3){
		f=1; 
		return 0;
	}
	return ans2;
} 
int main(){
	std::ios::sync_with_stdio(false);
	std::cin.tie(0);
	std::cout.tie(0); 
	int t;
	cin>>t;
	while(t--){
		cin>>n;
		f=0;
		m=0;
		for(int i=1;i<=n;i++){
			cin>>a[i];
			m+=a[i];
			v[i].clear(); 
		}
		for(int i=1;i<n;i++){
			int x,y;
			cin>>x>>y;
			v[x].push_back(y);
			v[y].push_back(x);
		}
		dfs(1,0);
		if(!f){
			cout<<"Yes";
		}
		else{
			cout<<"No";
		}
		cout<<'\n';
	}
	return 0;
} 
posted @ 2026-08-30 00:16  陈晨2011  阅读(5)  评论(0)    收藏  举报