wls的数据结构-树

二叉树


树的直径:最长的一条路径
树的中心:一条树的直径的中心点
树的中心的性质:是到所有到其他点路径最长的最小值,也就是直径的一半上取整
并且树的中心是唯一确定的(树的直径的长度是偶数的话唯二)
树的重心:选一个节点,当成根节点,他的儿子的子树大小最大值最小,这个节点就是重心
性质:当重心是根节点的时候,他下面每个子树的大小是不大于整棵树的一半的(反过来也是成立的, 
     并且可以发现如果有两个重心的,两个重心一定是连在一起的)
      重心到其他所有节点的距离和是最小的
// 求树的直径
#include<bits/stdc++.h>

using namespace std;
typedef long long LL;
const int N = 1e5+10;
vector<int> sons[N];
int dist[N];

void dfs1(int u, int fa){
    for(auto son : sons[u]){
        if(son == fa) continue;
        dist[son] = dist[u] + 1;
        dfs1(son, u);
    }
}

int main(){
    int n; scanf("%d", &n);
    for(int i = 1; i <= n - 1; i ++){
        int x, y; scanf("%d %d", &x, &y);
        sons[x].push_back(y);
        sons[y].push_back(x);
    }

    dfs1(1, -1);

    int lenmaxn = 0, lenid = 0;
    for(int i = 1; i <= n; i ++){
        if(dist[i] > lenmaxn) lenmaxn = dist[i], lenid = i;
    }
    dist[lenid] = 0;
    dfs1(lenid, -1);
    lenmaxn = 0, lenid = 0;
    for(int i = 1; i <= n; i ++){
        if(dist[i] > lenmaxn) lenmaxn = dist[i], lenid = i;
    }
    cout << lenmaxn << endl;
    return 0;
}

LCA

#include<bits/stdc++.h>

using namespace std;
typedef long long LL;
const int N = 100010;
vector<int> sons[N];
int father[N][21], dist[N];

void dfs(int u){
    for(auto v : sons[u]){
        dist[v] = dist[u] + 1;
        dfs(v);
    }
}

int main(){
    int n; scanf("%d", &n);
    for(int i = 1; i <= n - 1; i ++){
        int x, y; scanf("%d %d", &x, &y);
        sons[x].push_back(y);
        father[y][0] = x;
    }
    for(int i = 1; i <= 20; i ++){
        for(int j = 1; j <= n; j ++){
            if(father[father[j][i - 1]]) father[j][i] = father[father[j][i - 1]][i - 1];
        }
    }
    memset(dist, 0, sizeof dist);
    dfs(1);
    int m; scanf("%d", &m);
    while(m -- ){
        int x, y; scanf("%d %d", &x, &y);
        if(dist[x] < dist[y]) swap(x, y);
        int z = dist[x] - dist[y];
        for(int j = 0; z ; z /= 2, j ++){
            if(z & 1) x = father[x][j];
        }
        if(x == y){
            printf("%d\n", x);
            continue;
        }
        for(int j = 20; j >=0; j --){
            if(father[x][j] != father[y][j]) x = father[x][j], y = father[y][j];
        }
        printf("%d\n", father[x][0]);
    }
    return 0;   
}

posted @ 2022-04-01 17:57  牛佳文  阅读(91)  评论(0)    收藏  举报