1 /* ***********************************************
2 Author :kuangbin
3 Created Time :2013-11-17 14:30:29
4 File Name :E:\2013ACM\专题学习\树的分治\POJ1741.cpp
5 ************************************************ */
6
7 #include <stdio.h>
8 #include <string.h>
9 #include <iostream>
10 #include <algorithm>
11 #include <vector>
12 #include <queue>
13 #include <set>
14 #include <map>
15 #include <string>
16 #include <math.h>
17 #include <stdlib.h>
18 #include <time.h>
19 using namespace std;
20 const int MAXN = 10010;
21 const int INF = 0x3f3f3f3f;
22 struct Edge
23 {
24 int to,next,w;
25 }edge[MAXN*2];
26 int head[MAXN],tot;
27 void init()
28 {
29 tot = 0;
30 memset(head,-1,sizeof(head));
31 }
32 void addedge(int u,int v,int w)
33 {
34 edge[tot].to = v; edge[tot].w = w;
35 edge[tot].next = head[u];head[u] = tot++;
36 }
37 bool vis[MAXN];
38 int size[MAXN],dep[MAXN];
39 int le,ri;
40 int dfssize(int u,int pre)
41 {
42 size[u] = 1;
43 for(int i = head[u];i != -1;i = edge[i].next)
44 {
45 int v = edge[i].to;
46 if(v == pre || vis[v])continue;
47 size[u] += dfssize(v,u);
48 }
49 return size[u];
50 }
51 int minn;
52 //找重心
53 void getroot(int u,int pre,int totnum,int &root)
54 {
55 int maxx = totnum - size[u];
56 for(int i = head[u];i != -1;i = edge[i].next)
57 {
58 int v = edge[i].to;
59 if(v == pre || vis[v])continue;
60 getroot(v,u,totnum,root);
61 maxx = max(maxx,size[v]);
62 }
63 if(maxx < minn){minn = maxx; root = u;}
64 }
65 void dfsdepth(int u,int pre,int d)
66 {
67 dep[ri++] = d;
68 for(int i = head[u];i != -1;i = edge[i].next)
69 {
70 int v = edge[i].to;
71 if(v == pre || vis[v])continue;
72 dfsdepth(v,u,d+edge[i].w);
73 }
74 }
75 int k;
76 int getdep(int a,int b)
77 {
78 sort(dep+a,dep+b);
79 int ret = 0, e = b-1;
80 for(int i = a;i < b;i++)
81 {
82 if(dep[i] > k)break;
83 while(e >= a && dep[e] + dep[i] > k)e--;
84 ret += e - a + 1;
85 if(e > i)ret--;
86 }
87 return ret>>1;
88 }
89 int solve(int u)
90 {
91 int totnum = dfssize(u,-1);
92 int ret = 0;
93 minn = INF;
94 int root;
95 getroot(u,-1,totnum,root);
96 vis[root] = true;
97 for(int i = head[root];i != -1;i = edge[i].next)
98 {
99 int v = edge[i].to;
100 if(vis[v])continue;
101 ret += solve(v);
102 }
103 le = ri = 0;
104 for(int i = head[root];i != -1;i = edge[i].next)
105 {
106 int v = edge[i].to;
107 if(vis[v])continue;
108 dfsdepth(v,root,edge[i].w);
109 ret -= getdep(le,ri);
110 le = ri;
111 }
112 ret += getdep(0,ri);
113 for(int i = 0;i < ri;i++)
114 {
115 if(dep[i] <= k)ret++;
116 else break;
117 }
118 vis[root] = false;
119 return ret;
120 }
121
122 int main()
123 {
124 //freopen("in.txt","r",stdin);
125 //freopen("out.txt","w",stdout);
126 int n;
127 int u,v,w;
128 while(scanf("%d%d",&n,&k) == 2)
129 {
130 if(n == 0 && k == 0)break;
131 init();
132 for(int i = 1;i < n;i++)
133 {
134 scanf("%d%d%d",&u,&v,&w);
135 addedge(u,v,w);
136 addedge(v,u,w);
137 }
138 memset(vis,false,sizeof(vis));
139 printf("%d\n",solve(1));
140 }
141 return 0;
142 }

树的分治算法——基于点的分治

首先选取一个点将无根树转为有根树,再递归处理每一颗以根结点的儿子为根的子树。

给定一颗N(1<=N<=10000)个结点的带权树,定义dist(u,v)为u,v两点间的最短路径长度,路径的长度定义为路径上所有边的权和。

再给定一个K(1<=K<=10^9),如果对于不同的两个结点a,b,如果满足dist(a,b)<=K,则称(a,b)为合法点对。

求合法点对个数。

算法分析:

如果使用普通的DFS遍历,时间复杂度高达O(N^2),而使用时间复杂度为O(NK)的动态规划,更是无法在规定时限内出解的。

我们知道一条路径要么过根结点,要么在一颗子树中,这启发了我们可以使用分治算法。

路径在子树中的情况只需递归处理即可,下面我们来分析如何处理路径过根结点的情况。

记Depth(i)表示点i到根结点的路径长度,Belong(i)=X(X为根结点的某个儿子,且结点i在以X为根的子树内)。那么我们要统计的就是:

满足Depth(i)+Depth(j)<=K且Belong(i)!=Belong(j)的(i,j)个数

=满足Depth(i)+Depth(j)<=K的(i,j)个数

- 满足Depth(i)+Depth(j)<=K的(i,j)个数且Belong(i)==Belong(j)的(i,j)个数

而对于这两个部分,都是要求出满足Ai+Aj<=K的(i,j)的对数。将A排序后利用单调性可以得出一个O(N)的算法,所以可以用O(NlogN)的时间来解决这个问题。

综上,此题使用树的点分治算法时间复杂度为O(Nlog2N)。

所谓点分治,对于一条树路径,只有经过或不经过一个点的情况。

对于不经过的情况 把一棵树按这个点拆成好几棵分治就行了。

(楼天城男人八题,漆子超IOI2009国家集训队论文)

POJ1741——Tree(树的点分治)的更多相关文章

  1. 【poj1741】Tree 树的点分治

    题目描述 Give a tree with n vertices,each edge has a length(positive integer less than 1001). Define dis ...

  2. hdu 4812 D Tree(树的点分治)

    D Tree Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 102400/102400 K (Java/Others) Total ...

  3. [poj1741][tree] (树/点分治)

    Description Give a tree with n vertices,each edge has a length(positive integer less than 1001). Def ...

  4. POJ1741 Tree 树分治模板

    http://poj.org/problem?id=1741   题意:一棵n个点的树,每条边有距离v,求该树中距离小于等于k的点的对数.   dis[y]表示点y到根x的距离,v代表根到子树根的距离 ...

  5. POJ1741(SummerTrainingDay08-G 树的点分治)

    Tree Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 23380   Accepted: 7748 Description ...

  6. hdu4812-D Tree (树的点分治)

    昨天学了下树分治,今天补这道题,还是太不熟练了,写完之后一直超时.后来查出好多错= =比如v,u写倒了,比如+写成了取最值,比如....爆int...查了两个多小时的错..哭...(没想到进首页了 h ...

  7. 【POJ 1741】 Tree (树的点分治)

    Tree   Description Give a tree with n vertices,each edge has a length(positive integer less than 100 ...

  8. 树上点对统计poj1741(树的点分治)

    给定一棵树,边上有权值,要统计有多少对点路径的权值和<=k 分治算法在树的路径中的应用 这个论文里面有分析. 任意两点的路径,要么过根结点,要么在子树中.如果在子树中,那么只要递归处理就行了. ...

  9. POJ 1741 Tree(树的点分治,入门题)

    Tree Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 21357   Accepted: 7006 Description ...

随机推荐

  1. 【MySQL】自定义数据库连接池和开源数据库连接池的使用

    数据库连接池的概念 数据库连接背景 数据库连接是一种关键的.有限的.昂贵的资源,这一点在多用户的网页应用程序中体现得尤为突出.对数据库连接的管理能显著影响到整个应用程序的伸缩性和健壮性,影响到程序的性 ...

  2. 002 PCI Express体系结构(二)

    一.PCI总线的信号定义 PCI总线是一条共享总线,在一条PCI总线上可以挂接多个PCI设备.这些PCI设备通过一系列信号与PCI总线相连,这些信号由地址/数据信号.控制信号.仲裁信号.中断信号等多种 ...

  3. Spring系列之多个数据源配置

    前言 在上篇文章讲到了如何配置单数据源,但是在实际场景中,会有需要配置多个数据源的场景,比如说,我们在支付系统中,单笔操作(包含查询.插入.新增)中需要操作主库,在批量查询或者对账单查询等对实时性要求 ...

  4. 题解 b

    传送门 考场上只会暴力 \(n^4\) DP,部分分还写炸了 但其实这个DP可以前缀和优化到 \(n^3\) ,我觉得没有这档部分分就没写 但其实是有这一档的,我没有看出来-- 正解想不到 如果我们已 ...

  5. 题解 Equation

    传送门 考场上打了两个小时树剖,结果还是没搞出来 发现对于两个确定的点,它们一定可以列出一个方程来 其中系数的大小和正负只与这两点间距离的奇偶性有关 所以可以加一堆分情况讨论然后树剖 至于正解: 考虑 ...

  6. ASP.Net Core Web Api 使用 IdentityServer4 最新版 踩坑记录

    辅助工具 日志追踪包 : Serilog.AspNetCore 源码查看工具 : ILSpy 项目环境 ###: ASP.NetCore 3.1 IdentityServer4 4.0.0+ 主题内容 ...

  7. nuxt.js服务端渲染中less的配置和使用

    第一步:npm 安装 less 和 less-loader ,文件根目录下安装,指令如下 npm install less less-loader --save-dev 第二步:直接在组件中使用 &l ...

  8. Qt 中事件与处理

    一.事件与处理程序在运算过程中发生的一些事情:鼠标单击.键盘的按下...这些的事件的监控与处理在Qt中不是以信号的方式处理的.当这些事件发生时会调用QObject类中的功能函数(虚函数),所有的控件类 ...

  9. jq的常用事件及其案例

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  10. Clean Architecture For RazorPage 实现多语言和本地化

    最近终于把多语言功能加上了,这次就再发一篇,讲一下在asp.net core环境下如何实现多语言和本地化(Globalization and localization)功能,主要参看:ASP.NET ...