变换树根(树的遍历)

给定一个 n 个节点的树,节点编号为 1∼n。

树的根节点编号 r1 已知,每个节点(r1除外)的父节点编号 pi 已知。

现在,我们要重新指定树的根节点,更具体地说,我们要将树的根节点从 r1 变换为 r2。

请你计算并输出,变换树根后,每个节点(r2除外)的父节点编号。

输入格式

第一行包含三个整数 n,r1,r2,分别表示节点数量、原根节点编号、新根节点编号。

第二行包含 n−1 个整数,表示每个节点(r1 除外)的父节点编号 pi。

输入保证,编号越小的节点,其父节点编号越先给出。

输出格式

在一行中输出 n−1 个整数,表示变换树根后,每个节点(r2除外)的父节点编号。

输出应保证,编号越小的节点,其父节点编号越先输出。

数据范围

前 5 个测试点满足 2≤n≤10。
所有测试点满足 2≤n≤50000,1≤r1≠r2≤nn,1≤pi≤n。

输入样例1:

3 2 3
2 2

输出样例1:

2 3

输入样例2:

6 2 4
6 1 2 4 2

输出样例2:

6 4 1 4 2

 分析:先建个树,再从新的根开始遍历整个树。

代码1

#include<iostream>
#include<cstring>
using namespace std;

const int N = 50010,M = N*2;

int e[M],ne[M],h[N],idx,q[N];
int n,r1,r2;
void add(int a,int b)
{
    e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
void dfs(int u,int s)
{
    q[u]=s;//更新每个子节点的父亲
    for(int i=h[u];i!=-1;i=ne[i])
    {
        int j=e[i];
        if(j==s) continue;//搜到当前节点的父节点,跳过
        dfs(j,u);
    }
}
int main()
{
    scanf("%d%d%d",&n,&r1,&r2);
    memset(h,-1,sizeof h);
    for(int i=1;i<=n;i++)
    {
        int x;
        if(i!=r1)
        {
            scanf("%d",&x);
            add(i,x);
            add(x,i);
        }
    }
    dfs(r2,-1);
    for(int i=1;i<=n;i++)
    {
        if(i!=r2)
        cout<<q[i]<<" ";
    }
    return 0;
}
#include<bits/stdc++.h>
using namespace std;
const int N=1010101;
int a[N];
void find(int x,int s){//s是上一个节点的编号
    if(a[x]==x)
    {
        // cout<<x<<" &1 "<<end;l
        return;
    }
    // cout<<a[x]<<" "<<x<<" "<<s<<endl;
    find(a[x],x);
    // cout<<x<<" %2 "<<s<<endl;
    a[x]=s;//
    return;
}
int main(){
    int n,m,r1,r2;
    cin>>n>>r1>>r2;
    for(int i=1;i<=n;i++){
        int x;
        if(i==r1)continue;//等于r1,跳过
        cin>>x;
        a[i]=x;
    }
    find(a[r2],r2);
    for(int i=1;i<=n;i++){
        if(i==r2)continue;
        cout<<a[i]<<" ";
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值