Description
给定一棵有 n n n 个点的树和数列 a 1 , a 2 … a n a_1,a_2\dots a_n a1,a2…an,若 a i = − 1 a_i=-1 ai=−1 表示点 i i i 的值不确定,否则点 i i i 的值为非负整数 a i a_i ai。
你需要给每一个值不确定的点赋一个非负整数,使得该树满足以下条件:
- 设 m a x n x maxn_x maxnx 表示点 x x x 的儿子中的最大值,若有多个儿子都为 m a x n x maxn_x maxnx,则 x x x 的值为 m a x n x + 1 maxn_x+1 maxnx+1,否则 x x x 为 m a x n x maxn_x maxnx。
问是否存在一组解,存在输出 Reasonable
,不存在输出 Unreasonable
。
Solution
对于一个点
i
i
i,如果其不确定,则它的初始取值下界为 0
,上界为 1e9
,如果确定,上界为
a
i
a_i
ai,下界为
a
i
a_i
ai,设
u
i
u_i
ui 表示
i
i
i 的上界,
b
i
b_i
bi 表示
i
i
i 的下界。
遍历整棵树,对于点
x
x
x,求出儿子中最大的
b
s
o
n
x
b_{son_x}
bsonx(也就是
m
a
x
n
x
maxn_x
maxnx)以及数量
c
n
t
cnt
cnt 和最大的
u
s
o
n
x
u_{son_x}
usonx(设为
m
a
x
x
x
maxx_x
maxxx,其实只有 1e9
和
a
s
o
n
x
a_{son_x}
asonx 两种,也可以特判是否有不确定的点)。
b s o n x b_{son_x} bsonx 取最大是由 m a x n x maxn_x maxnx 的定义得出的,因为 b b b 是下界,下界取最大才是 m a x n x maxn_x maxnx 啊,这一点很关键,我在这卡了很久。
由 m a x n x maxn_x maxnx 的定义得出,此时的 m a x n x maxn_x maxnx 还要再加上 [ c n t > 1 ] [cnt>1] [cnt>1]。
若
a
x
=
−
1
a_x=-1
ax=−1,更新上下界,满足条件,记住一定要更新上下界,第三个测试点 WA
的可能是因为这个。
若 a x ≠ − 1 a_x\ne-1 ax=−1,分类讨论:
- a x = m a x n x a_x=maxn_x ax=maxnx,满足条件。
- a x < m a x n x a_x<maxn_x ax<maxnx,下界都比当前大,绝对不满足条件。
- a x > m a x n x a n d a x ≤ m a x x x a_x>maxn_x\ and\ a_x\le maxx_x ax>maxnx and ax≤maxxx,虽然已经确定的儿子的下界取不到,但是儿子中还有不确定的,将其改为 a x a_x ax 就满足条件了。
- a x > m a x n x a n d a x > m a x x x a_x>maxn_x\ and\ a_x>maxx_x ax>maxnx and ax>maxxx,不满足条件,因为儿子都确定了,所以无法改。
如此 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;
}