AcWing 6272:二叉树 ← 链式前向星 + dfs

【题目来源】
https://www.acwing.com/problem/content/6275/

https://www.luogu.com.cn/problem/P10722

【题目描述】
小杨有⼀棵包含 n 个节点的二叉树,且根节点的编号为 1。这棵二叉树任意⼀个节点要么是白色,要么是黑色。之后小杨会对这棵二叉树进行 q 次操作,每次小杨会选择⼀个节点,将以这个节点为根的子树内所有节点的颜色反转,即黑色变成白色,白色变成黑色。
小杨想知道 q 次操作全部完成之后每个节点的颜色。

【输入格式】
第⼀行一个正整数 n,表示二叉树的节点数量。
第二行 (
n−1) 个正整数,第 i(1≤i≤n−1)个数表示编号为 (i+1) 的节点的父亲节点编号,数据保证是⼀棵二叉树。
第三行一个长度为 n 的 01 串,从左到右第 i(
1≤i≤n)位如果为 0,表示编号为 i 的节点颜色为白色,否则为黑色。
第四行⼀个正整数 q,表示操作次数。
接下来 q 行每行⼀个正整数 ai(
1≤ai≤n),表示第 i 次操作选择的节点编号。

【输出格式】
输出一行一个长度为 n 的 01 串,表示 q 次操作全部完成之后每个节点的颜色。从左到右第 i(
1≤i≤n) 位如果为 0,表示编号为 i 的节点颜色为白色,否则为黑色。

【数据范围】
1≤n,q≤
10^5

【输入样例】
6
3 1 1 3 4
100101
3
1
3
2

【输出样例】
010000

【样例解释】
第一次操作后,节点颜色为:011010
第二次操作后,节点颜色为:000000
第三次操作后,节点颜色为:010000

【算法分析】
● 深度优先搜索(DFS)代码的具象化 → 探险家与迷宫:
https://blog.csdn.net/hnjzsyjyj/article/details/147073418

● dfs算法模板:https://blog.csdn.net/hnjzsyjyj/article/details/118736059
dfs算法常表现为复杂的递归函数形式,因此掌握递归是理解dfs算法的基础。

void dfs(int step) {
    判断边界 {
        输出解
    }

    尝试每一种可能 {
        满足check条件{
            标记
            继续下一步:dfs(step+1)
            恢复初始状态(回溯的时候要用到)
        }
    }
}

● yxc 图示“链式前向星”核心操作:https://blog.csdn.net/hnjzsyjyj/article/details/139369904
大佬 yxc 指出“链式前向星”就是“多单链表”,每条单链表基于“头插法”并用 e[]、ne[]、h[] 、val[] 等数组进行模拟创建。其中:
e[idx]:存储序号为 idx 的边的终点值
ne[idx]:存储序号为 idx 的边指向的边的序号(模拟链表指针)‌
h[a]:存储头结点 a 指向的边的序号
val[idx]:存储序号为 idx 的边的权值(可选)

【算法代码】

#include 
using namespace std;

const int N=1e5+5;
int h[N],e[N<<1],ne[N<<1],idx;
int cnt[N]; //times that a node has been operated

void add(int a,int b) {
    e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}

void dfs(int u,int num) {
    for(int i=h[u]; i!=-1; i=ne[i]) {
        int j=e[i];
        cnt[j]+=num;
        dfs(j,cnt[j]);
    }
}

int main() {
    int n;
    cin>>n;
    memset(h,-1,sizeof h);
    for(int i=2; i<=n; i++) {
        int idx;
        cin>>idx;
        add(idx,i);
    }

    string s;
    int q;
    cin>>s>>q;
    while(q--) {
        int x;
        cin>>x;
        cnt[x]++;
    }

    dfs(1,cnt[1]);
    for(int i=1; i<=n; i++) { //Even is white, odd is black.
        if(cnt[i]%2==0) s[i-1]=='1'?cout<<1:cout<<0;
        else s[i-1]=='1'?cout<<0:cout<<1;
    }

    return 0;
}

/*
in:
6
3 1 1 3 4
100101
3
1
3
2

out:
010000
*/





【参考文献】
https://blog.csdn.net/hnjzsyjyj/article/details/147177515
https://www.acwing.com/solution/content/277371/
https://blog.csdn.net/hnjzsyjyj/article/details/139369904




 

你可能感兴趣的:(信息学竞赛,#,图论,图,链式前向星)