1 条题解
-
0
自动搬运
来自洛谷,原作者为

Larryyu
Euphoric NocturNe |AS| ALTERing EGO搬运于
2025-08-24 22:47:53,当前版本为作者最后更新于2023-10-11 21:57:17,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
Description
给定一棵有 个点的树和数列 ,若 表示点 的值不确定,否则点 的值为非负整数 。
你需要给每一个值不确定的点赋一个非负整数,使得该树满足以下条件:
- 设 表示点 的儿子中的最大值,若有多个儿子都为 ,则 的值为 ,否则 为 。
问是否存在一组解,存在输出
Reasonable,不存在输出Unreasonable。Solution
对于一个点 ,如果其不确定,则它的初始取值下界为
0,上界为1e9,如果确定,上界为 ,下界为 ,设 表示 的上界, 表示 的下界。遍历整棵树,对于点 ,求出儿子中最大的 (也就是 )以及数量 和最大的 (设为 ,其实只有
1e9和 两种,也可以特判是否有不确定的点)。取最大是由 的定义得出的,因为 是下界,下界取最大才是 啊,这一点很关键,我在这卡了很久。
由 的定义得出,此时的 还要再加上 。
若 ,更新上下界,满足条件,记住一定要更新上下界,第三个测试点
WA的可能是因为这个。若 ,分类讨论:
- ,满足条件。
- ,下界都比当前大,绝对不满足条件。
- ,虽然已经确定的儿子的下界取不到,但是儿子中还有不确定的,将其改为 就满足条件了。
- ,不满足条件,因为儿子都确定了,所以无法改。
如此
dfs即可。Code
#include<bits/stdc++.h> using namespace std; #define inf 2000000000 int t; int n; int tot,head[100010]; int a[100010],b[100010],u[100010]; //a原数值,b下界,u上界 struct edge{ int to,next; }e[200010]; void add(int x,int y){ e[++tot].to=y; e[tot].next=head[x]; head[x]=tot; } void clean(){ //多测清空 tot=0; for(int i=1;i<=n;i++){ head[i]=0; } } bool dfs(int x,int fax){ int maxn=-10,cnt=0,maxx=-10; for(int i=head[x];i;i=e[i].next){ int y=e[i].to; if(y==fax) continue; if(!dfs(y,x)) return 0; //儿子都已经不满足条件了,可以直接退出 if(b[y]>maxn){ maxn=b[y]; cnt=1; }else if(b[y]==maxn){ cnt++; } maxx=max(maxx,u[y]); } if(maxn==-10){ //叶子节点 return 1; } maxn=maxn+(cnt>1); if(a[x]!=-1){ if(a[x]<maxn) return 0; else if(a[x]==maxn) return 1; else if(a[x]<=maxx) return 1; else return 0; } if(a[x]==-1){ u[x]=maxx; b[x]=maxn; return 1; } } void solve(){ clean(); cin>>n; for(int i=1;i<=n;i++){ cin>>a[i]; if(a[i]==-1) u[i]=inf,b[i]=0; else b[i]=u[i]=a[i]; } for(int i=1;i<n;i++){ int x,y; cin>>x>>y; add(x,y); add(y,x); } if(dfs(1,0)) cout<<"Reasonable"<<endl; else cout<<"Unreasonable"<<endl; } int main(){ cin>>t; while(t--){ solve(); } return 0; }
- 1
信息
- ID
- 8816
- 时间
- 1000ms
- 内存
- 512MiB
- 难度
- 4
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者