树的讲解+练习(二)

今天我们继续昨天树的讲解与练习,废话不多说,现在开始

目录

C. 树的最近公共祖先1(LCA)

题目描述

输入格式

输出格式

样例输入    Copy

样例输出     Copy

数据规模

思路:

树上染色1(因为还有2和3)

题目描述

输入格式

输出格式

样例输入    Copy

样例输出     Copy

数据规模

提示:

最后


C. 树的最近公共祖先1(LCA)

题目描述

给你一棵 𝑛个节点的以 11 号节点为根的树,节点的编号为 1 到 𝑛。现在有 𝑚 组询问,对于每组询问 𝑢,𝑣,请求出 𝑢 号节点和 𝑣 号节点的最近公共祖先(Lowest Common Ancestor)。

输入格式

第一行一个整数 𝑛 表示节点数。

接下来 𝑛−1 行,每行两个整数 𝑥,𝑦 表示 𝑥 号节点是 𝑦 号节点的父亲节点。

输入保证是一棵树。

接下来一行一个整数 𝑚 表示询问数。

接下来 𝑚 行,每行两个整数 𝑢,𝑣 表示一组询问。

输出格式

输出共 𝑚 行,对于每组询问,输出一行一个整数表示对应的两个点的最近公共祖先的编号。

样例输入    Copy
4
1 2
2 3
1 4
3
1 2
2 3
2 4
样例输出     Copy
1
2
1
数据规模

对于所有数据,保证 1≤𝑛,𝑚≤1000,1≤𝑢,𝑣≤𝑛。

思路:

        首先,我们在题目中我们可以发现,这个我们可以判断这两个点是否在同一层上,如果这两个点在同一层上,我们可以让这两个点同时上升一层,直到这两个点同时到达同一个点,然后输出这两个点此时的节点编号;如果这两个点不在同一层,那就让更深的那一个节点上升一层,直到这两个点到达同一层,然后再让这两个点同时上升一层,直到这两个点到达同一层,

 然后输出此时两个点节点编号,因为此时两个点是在同一层上,也就找到了他们的最近公共祖先, 就结束了。

#include<bits/stdc++.h>
using namespace std;
int m,n;
int fa[100005];
int d[100005];
vector<int> cl[100005];
void dfs(int x) {
    d[x]=d[fa[x]]+1;
    for(auto y:cl[x]) {
        dfs(y);
    }
}
int LAC(int x,int y) {
    if(d[x]<d[y]) {
        swap(x,y);
    }
    while(d[x]>d[y]) {
        x=fa[x];
    }
    while(x!=y) {
        x=fa[x];
        y=fa[y];
    }
    return x;
}
int main() {
    cin>>n;
    for(int i=1,x,y;i<n;i++) {
        cin>>x>>y;
        cl[x].push_back(y);
        fa[y]=x;
    }
    dfs(1);
    cin>>m;
    while(m--) {
        int u,v;
        cin>>u>>v;
        cout<<LAC(u,v)<<"\n";
    }
    return 0;
}

树上染色1(因为还有2和3)

题目描述

给你一棵 𝑛 个节点的以 1 号节点为根的树,节点的编号为 1 到 𝑛。一开始树上所有节点都是白色的,每次操作我们可以选择一个节点 𝑥,并把根节点到节点 𝑥 的路径上的所有点都染成黑色。请问最少需要操作多少次,可以把树上所有节点都染黑?

输入格式

第一行一个整数 𝑛 表示节点数。

接下来 𝑛−1 行,每行两个整数 𝑥,𝑦 表示 𝑥 号节点是 𝑦 号节点的父亲节点。

输入保证是一棵树。

输出格式

输出一行一个整数表示答案。

样例输入    Copy
5
1 2
1 3
1 4
3 5
样例输出     Copy
3
数据规模

对于所有数据,保证 1≤𝑛≤10^{6}

提示:

        这个树上染色的题目,我们除了要用dfs来进行深搜,我们还要用一些贪心
首先,这个题他要进行染色,而且他还是要从这个节点到根节点都能染成黑色,所以我们可以发现,这个题我们可以让当前的节点是叶子节点,这样我们就可以让从叶子节点到根节点的这一条路径全被染成黑色,来保证我们染色的次数最少。

最后一道题就当检测了,做完可以私信我

最后

        希望大家可以学到一定的知识,我们下期再见

  • 16
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值