利用DFS序求树中以某点为根节点的子树

定义 :在一棵树中,每一个节点在dfs深度优先遍历的时间序列(将树形结构转化为线性结构)

利用DFS序求树中以某点为根节点的子树_第1张图片
利用DFS序求树中以某点为根节点的子树_第2张图片

核心代码及数据结构

vector<int> tree[100];   //存放的栈,为什么不用数组?因为栈好处理
int in[100];    //进入的时间戳
int out[100];    //出去的时间戳
int num[200];    //存放树dfs序列||树的前序遍历
int t = 0;        //记录序列的时间

void dfs(int x, int fa) {
    in[x] = ++t; //进入的时间戳
    num[t] = x;  //生成新的线性结构
    for(int i = 0; i < tree[x].size(); i++) {
        int cnt = tree[x][i];
        if(cnt == fa) continue;
        dfs(cnt, x);
    }
    out[x] = t;  //出去的时间戳
}

题目:求树中以某点为根节点的子树

代码

#include 
using namespace std;
vector<int> tree[100];   //存放的栈,为什么不用数组?因为栈好处理
int in[100];    //进入的时间戳
int out[100];    //出去的时间戳
int num[200];    //存放树dfs序列||树的前序遍历
int t = 0;        //记录序列的时间


void dfs(int x, int fa) {
    in[x] = ++t; //进入的时间戳
    num[t] = x;  //生成新的线性结构
    for(int i = 0; i < tree[x].size(); i++) {
        int cnt = tree[x][i];
        if(cnt == fa) continue;
        dfs(cnt, x);
    }
    out[x] = t;  //出去的时间戳
}
int main()
{
    int n;  //n表示多少结点
    int u, v;
    int r,op; //r表示以某点作为子树的根节点,op表示询问多少次数
    while(scanf("%d %d", &n,&op) != EOF)
    {
        for(int i = 0; i < n-1; i++)
        {
            scanf("%d %d", &u, &v);
            tree[u].push_back(v);
            tree[v].push_back(u);
        }
        dfs(1, -1);
        
        //显示数组
        /*
        for(int i=1;in[i]!=0;i++)
        {
            cout<
        while(op--)
        {
            cin>>r;
            for(int i=in[r];i<=out[r];i++)
            {
                cout<<num[i];
            }
            cout<<endl;
        }
    }
    return 0;
}

运行结果

利用DFS序求树中以某点为根节点的子树_第3张图片

题目:

有一棵点数为 N 的树,以点 1 为根,且树点有边权。然后有 M 个操作,分为三种:
操作 1 :把某个节点 r 的点权增加 s 。
操作 2 :把某个节点 r 为根的子树中所有点的点权都增加 s 。
操作 3 :查询以第r节点为根节点的子树
操作4:查询以第r节点为根节点的子树节点和

代码

#include 

using namespace std;


vector<int> tree[100];   //存放的栈,为什么不用数组?因为栈好处理
int in[100];    //进入的时间戳
int out[100];    //出去的时间戳
int num[200];    //存放树dfs序列||树的前序遍历
int t = 0;        //记录序列的时间

void dfs(int x, int fa) {
    in[x] = ++t; //进入的时间戳
    num[t] = x;  //生成新的线性结构
    for(int i = 0; i < tree[x].size(); i++) {
        int cnt = tree[x][i];
        if(cnt == fa) continue;
        dfs(cnt, x);
    }
    out[x] = t;  //出去的时间戳
}
int main()
{
    int n,m;  //n表示多少结点
    int u, v;
    int r,op,s; //r表示以某点作为子树的根节点,op表示询问多少次数
    while(scanf("%d %d", &n,&m) != EOF)
    {
        for(int i = 0; i < n-1; i++)
        {
            scanf("%d %d", &u, &v);
            tree[u].push_back(v);
            tree[v].push_back(u);
        }
        dfs(1, -1);

        //显示数组
        /*
        cout<<"第i节点子树的入栈时间:";
        for(int i=1;in[i]!=0;i++)
        {
            cout<
       while(m--)
        {
            cin>>op;
            if(op==1) //op==1时,以第r节点加s
            {
                cin>>r>>s;
                num[r] = num[r]+s;
            }
            if(op==2)  //op==2时,以第r节点为根节点的子树节点加s
            {
                cin>>r>>s;
                for(int i=in[r];i<=out[r];i++)
                {
                    num[i]= num[i]+s;
                }
            }
            if(op==3) //op==3时,查询以第r节点为根节点的子树
            {
                cin>>r;
                for(int i=in[r];i<=out[r];i++)
                {
                    cout<<num[i];
                }
                cout<<endl;
            }
            if(op==4) //op==4时,查询以第r节点为根节点的子树的节点和
            {
                cin>>r;
                int sum=0;
                for(int i=in[r];i<=out[r];i++)
                {
                    sum= sum+num[i];
                }
                cout<<sum<<endl;
            }
        }
    }
    return 0;
}

运行结果

利用DFS序求树中以某点为根节点的子树_第4张图片

你可能感兴趣的:(DFS)