1 条题解

  • 0
    @ 2025-8-24 22:47:53

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar Larryyu
    Euphoric NocturNe |AS| ALTERing EGO

    搬运于2025-08-24 22:47:53,当前版本为作者最后更新于2023-10-11 21:57:17,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    Description

    给定一棵有 nn 个点的树和数列 a1,a2ana_1,a_2\dots a_n,若 ai=1a_i=-1 表示点 ii 的值不确定,否则点 ii 的值为非负整数 aia_i

    你需要给每一个值不确定的点赋一个非负整数,使得该树满足以下条件:

    • maxnxmaxn_x 表示点 xx 的儿子中的最大值,若有多个儿子都为 maxnxmaxn_x,则 xx 的值为 maxnx+1maxn_x+1,否则 xxmaxnxmaxn_x

    问是否存在一组解,存在输出 Reasonable,不存在输出 Unreasonable

    Solution

    对于一个点 ii,如果其不确定,则它的初始取值下界为 0,上界为 1e9,如果确定,上界为 aia_i,下界为 aia_i,设 uiu_i 表示 ii 的上界,bib_i 表示 ii 的下界。

    遍历整棵树,对于点 xx,求出儿子中最大的 bsonxb_{son_x}(也就是 maxnxmaxn_x)以及数量 cntcnt 和最大的 usonxu_{son_x}(设为 maxxxmaxx_x,其实只有 1e9asonxa_{son_x} 两种,也可以特判是否有不确定的点)。

    bsonxb_{son_x} 取最大是由 maxnxmaxn_x 的定义得出的,因为 bb 是下界,下界取最大才是 maxnxmaxn_x 啊,这一点很关键,我在这卡了很久。

    maxnxmaxn_x 的定义得出,此时的 maxnxmaxn_x 还要再加上 [cnt>1][cnt>1]

    ax=1a_x=-1,更新上下界,满足条件,记住一定要更新上下界,第三个测试点 WA 的可能是因为这个。

    ax1a_x\ne-1,分类讨论:

    • ax=maxnxa_x=maxn_x,满足条件。
    • ax<maxnxa_x<maxn_x,下界都比当前大,绝对不满足条件。
    • ax>maxnx and axmaxxxa_x>maxn_x\ and\ a_x\le maxx_x,虽然已经确定的儿子的下界取不到,但是儿子中还有不确定的,将其改为 axa_x 就满足条件了。
    • ax>maxnx and ax>maxxxa_x>maxn_x\ and\ a_x>maxx_x,不满足条件,因为儿子都确定了,所以无法改。

    如此 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
    上传者