poj 1741 Tree(点分治)

本文详细解析了一道树上分治的经典模版题,通过不断寻找树的重心并判断经过重心路径是否满足条件,实现了点分治算法。文章提供了完整的代码实现,包括初始化、添加边、深度优先搜索等关键步骤,并解释了如何找到子树数量、确定重心及计算路径数量。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接:http://poj.org/problem?id=1741

 

题解:一道点分治的模版题,直线上的分治就没什么好说了简单的这是一道树上的分治模版题

其实分治就是和二分差不多,树上的分治也就是不断的找树的重心然后再找经过重心的有几条路是满足条件的。树上的分治有具体的解析可以去看看理解一下挺简单的,然后差不多树上的分治都可以利用这个模版然后稍微改一下就好。

#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
const int M = 1e4 + 10;
struct Edge {
    int u , v , w , next;
}edge[M << 1];
int head[M] , e , Size , n , ans , k;
bool vis[M];
void init() {
    memset(head , -1 , sizeof(head));
    memset(vis , false , sizeof(vis));
    ans = e = 0;
}
void add(int u , int v , int w) {
    edge[e].v = v;
    edge[e].next = head[u];
    edge[e].w = w;
    head[u] = e++;
}
int size[M] , root , mx[M];
//////
void dfs_size(int u , int fa)
{
    size[u] = 1;
    mx[u] = 0;
    for(int i = head[u] ; ~i ; i = edge[i].next) {
        int v = edge[i].v;
        if(v != fa && !vis[v])
        {
            dfs_size(v, u);
            size[u] += size[v];
            if(size[v] > mx[u]) mx[u] = size[v];
        }
    }
}//找子树包括自生的个数
void dfs_root(int r, int u, int fa) {
    if(size[r] - size[u] > mx[u]) mx[u] = size[r] - size[u];
    if(mx[u] < Size) Size = mx[u], root = u;
    for(int i = head[u] ; ~i ; i = edge[i].next) {
        int v = edge[i].v;
        if(v != fa && !vis[v]) dfs_root(r, v, u);
    }
}//找重心
void get_root(int u , int pre) {
    dfs_size(u , pre);
    dfs_root(u , u , pre);
}
//////
int num = 0 , dis[M];
void find_dis(int u , int pre , int deep) {
    dis[num++] = deep;
    for(int i = head[u] ; ~i ; i = edge[i].next) {
        int v = edge[i].v;
        if(vis[v] || v == pre) continue;
        find_dis(v , u , deep + edge[i].w);
    }
}
int cau(int u , int pre , int deep) {
    num = 0;
    find_dis(u , pre , deep);
    int sum = 0;
    sort(dis , dis + num);
    int l = 0 , r = num - 1;
    while(l < r) {
        while(dis[l] + dis[r] > k && l < r) r--;
        sum += (r - l);
        l++;
    }
    return sum;
}//这里的cau只要改一下就能解其他类似的点分治问题
void dfs(int u) {
    Size = n;
    get_root(u , -1);
    vis[root] = true;
    ans += cau(root , -1 , 0);
    int rt = root;
    for(int i = head[root] ; ~i ; i = edge[i].next) {
        int v = edge[i].v;
        if(vis[v]) continue;
        ans -= cau(v , rt , edge[i].w);//这里为什么减去要理解一下然后就没什么问题了
        dfs(v);
    }
}
int main() {
    while(~scanf("%d%d" , &n , &k)) {
        if(n == 0 && k == 0) break;
        init();
        for(int i = 0 ; i < n - 1 ; i++) {
            int u , v , l;
            scanf("%d%d%d" , &u , &v , &l);
            add(u , v , l);
            add(v , u , l);
        }
        dfs(1);
        printf("%d\n" , ans);
    }
    return 0;
}

 

转载于:https://www.cnblogs.com/TnT2333333/p/7745400.html

标题基于SpringBoot+Vue的社区便民服务平台研究AI更换标题第1章引言介绍社区便民服务平台的研究背景、意义,以及基于SpringBoot+Vue技术的研究现状和创新点。1.1研究背景与意义分析社区便民服务的重要性,以及SpringBoot+Vue技术在平台建设中的优势。1.2国内外研究现状概述国内外在社区便民服务平台方面的发展现状。1.3研究方法与创新点阐述本文采用的研究方法和在SpringBoot+Vue技术应用上的创新之处。第2章相关理论介绍SpringBoot和Vue的相关理论基础,以及它们在社区便民服务平台中的应用。2.1SpringBoot技术概述解释SpringBoot的基本概念、特点及其在便民服务平台中的应用价值。2.2Vue技术概述阐述Vue的核心思想、技术特性及其在前端界面开发中的优势。2.3SpringBoot与Vue的整合应用探讨SpringBoot与Vue如何有效整合,以提升社区便民服务平台的性能。第3章平台需求分析与设计分析社区便民服务平台的需求,并基于SpringBoot+Vue技术进行平台设计。3.1需求分析明确平台需满足的功能需求和性能需求。3.2架构设计设计平台的整体架构,包括前后端分离、模块化设计等思想。3.3数据库设计根据平台需求设计合理的数据库结构,包括数据表、字段等。第4章平台实现与关键技术详细阐述基于SpringBoot+Vue的社区便民服务平台的实现过程及关键技术。4.1后端服务实现使用SpringBoot实现后端服务,包括用户管理、服务管理等核心功能。4.2前端界面实现采用Vue技术实现前端界面,提供友好的用户交互体验。4.3前后端交互技术探讨前后端数据交互的方式,如RESTful API、WebSocket等。第5章平台测试与优化对实现的社区便民服务平台进行全面测试,并针对问题进行优化。5.1测试环境与工具介绍测试
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值