首页 > 其他分享 >洛谷P4178 Tree 题解 树上点分治

洛谷P4178 Tree 题解 树上点分治

时间:2023-06-25 19:57:29浏览次数:62  
标签:vis 洛谷 get int 题解 Tree v1 v2 auto

题目链接:https://www.luogu.com.cn/problem/P4178

解题思路:

点分治模板题。

设当前重心为 \(u\),一共有三种不同类型的路径:

  1. 路径的一个端点恰好是重心 \(u\);
  2. 路径的两个端点在 \(u\) 的不同子树中;
  3. 路径的两个端点在 \(u\) 的同一个子树中。

找到重心 \(u\) 之后,前两类路径分开求。第三类路径分治求。

示例程序:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 4e4 + 5;

struct Edge {
    int v, w;
};
vector<Edge> g[maxn];
int n, K, ans;
bool vis[maxn];

int get_size(int u, int p) {
    if (vis[u]) return 0;
    int sum = 1;
    for (auto e : g[u])
        if (e.v != p)
            sum += get_size(e.v, u);
    return sum;
}

int get_wc(int u, int p, int tot, int &wc) {
    if (vis[u]) return 0;
    int sum = 1, ms = 0;
    for (auto e : g[u]) {
        int v = e.v;
        if (v == p) continue;
        int tmp = get_wc(v, u, tot, wc);
        ms = max(ms, tmp);
        sum += tmp;
    }
    ms = max(ms, tot - sum);
    if (ms <= tot / 2) wc = u;
    return sum;
}

void get_dfs(int u, int p, int dis, vector<int> &v) {
    if (vis[u] || dis > K) return;
    v.push_back(dis);
    for (auto e : g[u])
        if (e.v != p)
            get_dfs(e.v, u, dis + e.w, v);
}

void dfs(int u) {
    if (vis[u]) return;
    get_wc(u, -1, get_size(u, -1), u);
    vis[u] = true;
    vector<int> v1, v2;
    for (auto e : g[u])
        get_dfs(e.v, u, e.w, v1);
    sort(v1.begin(), v1.end());
    int tmp = 0;
    for (auto e : g[u]) {
        v2.clear();
        get_dfs(e.v, u, e.w, v2);
        sort(v2.begin(), v2.end());
        for (auto d : v2) {
            int num1 = upper_bound(v1.begin(), v1.end(), K - d) - v1.begin();
            int num2 = upper_bound(v2.begin(), v2.end(), K - d) - v2.begin();
            tmp += num1 - num2;
        }
    }
    ans += v1.size();
    ans += tmp / 2;

    for (auto e : g[u])
        dfs(e.v);
}

int main() {
    scanf("%d", &n);
    for (int i = 1; i < n; i++) {
        int u, v, w;
        scanf("%d%d%d", &u, &v, &w);
        g[u].push_back({v, w});
        g[v].push_back({u, w});
    }
    scanf("%d", &K);
    dfs(1);
    printf("%d\n", ans);
    return 0;
}

标签:vis,洛谷,get,int,题解,Tree,v1,v2,auto
From: https://www.cnblogs.com/quanjun/p/17503800.html

相关文章

  • CodeForces 1842F Tenzing and Tree
    洛谷传送门CF传送门事实上自己方向一直是错的……绝对值不好弄,我一开始的想法是直接去绝对值,但是不可避免地要\(O(n^3)\)。考虑我们直接钦定黑点重心为根,设这个根为\(r\),设\(sz_i\)为\(i\)子树内黑点数,由重心的性质,可以直接去绝对值,也就是说答案为\(\sum\limits_{i\n......
  • sourcetree Authentication failed
    sourcetree的git密码存在mac的钥匙串里面,需要在钥匙串里删除掉对应信息,再次打开就会让你重新输入密码,问题就解决了。参看:https://stackoverflow.com/questions/20953940/authentication-failed-to-bitbucket......
  • B+ tree implemented in Java
    B+树相关介绍B+树是一棵多叉排序树,即每个非叶子节点可以包含多个子节点,其整体结构呈扁平化,所以其非常适配于数据库和操作系统的文件系统中。且B+树能够保持数据的稳定有序,插入和删除都拥有较稳定的对数时间复杂度。B+树的特性:以m阶为例,m表示内部节点即非叶子节点可以包含的......
  • 基于uni-app+vue3渲染markdown格式|uniapp软键盘顶起问题解决方案
    前些时候有给大家分享一篇uni-app+vite4+uview-plus搭建跨端项目。今天主要分享下在uniapp中渲染markdown语法及uniapp中软键盘弹起,页面tabbar或顶部自定义navbar导航栏被撑起挤压的问题。如上图:支持h5+小程序+App端markdown解析渲染。上面则是演示了在App端+小程序端键盘弹......
  • Codeforces Round 875 (Div. 2) C. Copil Copac Draws Trees
    bfs解法如果是暴力求解的话就每次都扫描一次所有边直到所有点都和树连接优化:每次扫描我们可以发现会重复扫描那些已经存在树中的边了,因此我们可以只扫描还没有存在树中的边且是没扫过的边对于每次更新,比如由点a已经在树中,更新点b,我们只需判断点a被更新到树中点的编号和a-b边的......
  • LOJ#6077. 「2017 山东一轮集训 Day7」逆序对题解
    考虑朴素dp,令\(f_{i,j}\)为\(1\simi\)排列有\(j\)个逆序对的排列数。有转移方程:\[f_{i,j}=\sum_{k=0}^{i-1}f_{i-1,j-k}\]特殊地,我们定义\(j<0\)的\(f_{i,j}\)为\(0\)。定义\(\displaystyleF_i(x)=\sum_{j=0}^{\infty}f_{i,j}x^j\),有\(\displaystyleF_{i}(x)=......
  • CF771C Bear and Tree Jumps
    CF771CBearandTreeJumpslink赛时脑子抽了没想出来,其实思路已经沾边了,但是……唉,还是太菜了qwq。题意:给你一颗有\(n\)个点的树,和每次能走的最大步数\(K\),求所有点对相互到达的最小步数之和。思路:首先第一步转化很简单:设点\(u,v\)在树上的距离为\(d\),则\(u,v\)......
  • AGC021E Ball Eat Chameleons 题解
    本文网址:https://www.cnblogs.com/zsc985246/p/17501300.html,转载请注明出处。传送门AGC021EBallEatChameleons题目翻译有\(n\)只变色龙,一开始都是蓝色。你会依次扔出\(k\)个球,每次扔出都要指定一只变色龙吃掉这个球。扔出的球可以是红色或蓝色。变色龙从蓝色变成红......
  • 【Debian】更换阿里源出现的Certificate问题解决方法
    系统版本Debian11源配置debhttps://mirrors.aliyun.com/debian/bullseyemainnon-freecontribdeb-srchttps://mirrors.aliyun.com/debian/bullseyemainnon-freecontribdebhttps://mirrors.aliyun.com/debian-security/bullseye-securitymaindeb-src......
  • [ABC259F] Select Edges 题解
    Solution考虑树形\(dp\)。我们可以注意到节点\(i\)的相邻的边中被选中的不超过\(d_i\)条,显然我们可以定义状态\(dp_{u,k}\)表示节点\(u\)连接子节点的边有\(k\)条的最大值。但是此处没有给定\(d_i\)的范围,所以对于一个节点最多可能会有\(n-1\)个点,所以时间复杂......