Tree POJ - 1741

Tree

POJ - 1741

shu de dian fen zhi

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 using namespace std;
 6 const int maxn = 1e5 + 10;
 7 const int inf = 0x3f3f3f3f;
 8 int n, k;
 9 int rt, snode, ans;
10 int size[maxn], d[maxn], vis[maxn];
11 int dep[maxn];
12 int maxson[maxn];
13 struct Edge{
14     int v, w, nxt;
15     Edge(int v = 0, int w = 0, int nxt = 0) : v(v), w(w), nxt(nxt) {}
16 }e[maxn<<1];
17 int head[maxn], cnt;
18 void init(){
19     cnt = 0;
20     memset(head, -1, sizeof head);
21 }
22 void add(int u, int v, int w){
23     e[cnt] = Edge(v, w, head[u]);
24     head[u] = cnt++;
25 }
26
27 void getrt(int u, int f){
28     size[u] = 1;
29     maxson[u] = 0;
30     for(int i = head[u]; ~i; i = e[i].nxt){
31         int v = e[i].v;
32         if(v == f || vis[v]) continue;
33         getrt(v, u);
34         size[u] += size[v];
35         maxson[u] = max(maxson[u], size[v]);
36     }
37     maxson[u] = max(maxson[u], snode - size[u]);
38     if(maxson[u] < maxson[rt])  rt = u;
39 }
40 void getdep(int u, int f){
41     dep[++dep[0]] = d[u];
42     for(int i = head[u]; ~i; i = e[i].nxt){
43         int v = e[i].v;
44         if(v == f || vis[v]) continue;
45         d[v] = d[u] + e[i].w;
46         getdep(v, u);
47     }
48 }
49 int cal(int u, int w){
50     d[u] = w;
51     dep[0] = 0;
52     getdep(u, 0);
53     sort(dep + 1, dep + 1 + dep[0]);
54     int sum = 0;
55     int l =  1, r = dep[0];
56     while(l < r){
57         if(dep[l] + dep[r] <= k) {
58             sum += r - l;
59             l++;
60         }else r--;
61     }
62     return sum;
63 }
64
65 void solve(int u){
66     vis[u] =  1;
67     ans += cal(u, 0);
68     for(int i = head[u]; ~i; i = e[i].nxt){
69         int v = e[i].v;
70         if(vis[v]) continue;
71         ans -= cal(v, e[i].w);
72         rt = 0;
73         snode = size[v];
74         getrt(v, u);
75         solve(rt);
76     }
77 }
78
79 int main(){
80     while(scanf("%d %d", &n, &k) && (n || k)){
81         init();
82         memset(vis, 0, sizeof vis);
83         int u, v, w;
84         for(int i = 1; i < n; i++){
85             scanf("%d %d %d", &u, &v, &w);
86             add(u, v, w);
87             add(v, u, w);
88         }
89         rt = ans = 0;
90         snode = n;
91         maxson[0] = inf;
92         getrt(1, 0);
93         solve(rt);
94         printf("%d\n", ans);
95     }
96
97 }

原文地址:https://www.cnblogs.com/yijiull/p/8335195.html

时间: 2024-11-05 23:31:11

Tree POJ - 1741的相关文章

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

Tree Description Give a tree with n vertices,each edge has a length(positive integer less than 1001). Define dist(u,v)=The min distance between node u and v. Give an integer k,for every pair (u,v) of vertices is called valid if and only if dist(u,v)

Poj 1741 Tree (树的分治)

题目链接: Poj 1741 Tree 这个题目Tle的好苦啊,原来一直是树的重心没找对,Tle好长时间,终于对了,好感动,先贴个代码. 1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 using namespace std; 6 7 const int maxn = 10010; 8 struct node 9 { 10 int

poj 1741 Tree(树的点分治)

poj 1741 Tree(树的点分治) 给出一个n个结点的树和一个整数k,问有多少个距离不超过k的点对. 首先对于一个树中的点对,要么经过根结点,要么不经过.所以我们可以把经过根节点的符合点对统计出来.接着对于每一个子树再次运算.如果不用点分治的技巧,时间复杂度可能退化成\(O(n^2)\)(链).如果对于子树重新选根,找到树的重心,就一定可以保证时间复杂度在\(O(nlogn)\)内. 具体技巧是:首先选出树的重心,将重心视为根.接着计算出每个结点的深度,以此统计答案.由于子树中可能出现重复

POJ 1741 Tree (树上点分治)(楼教主男人八题之一)

题目地址:POJ 1741 树分治第一发! 树分治详情请看漆子超的国家集训队论文,论文传送门 树分治裸题. 代码如下: #include <iostream> #include <string.h> #include <math.h> #include <queue> #include <algorithm> #include <stdlib.h> #include <map> #include <set> #

【点分治】【POJ 1741】【cogs 1714】树上的点对

1714. [POJ1741][男人八题]树上的点对 ★★★ 输入文件:poj1741_tree.in 输出文件:poj1741_tree.out 简单对比 时间限制:1 s 内存限制:256 MB [题目描述] 给一棵有n个节点的树,每条边都有一个长度(小于1001的正整数). 定义dist(u,v)=节点u到节点v的最短路距离. 给出一个整数k,我们称顶点对(u,v)是合法的当且仅当dist(u,v)不大于k. 写一个程序,对于给定的树,计算有多少对顶点对是合法的. [输入格式] 输入包含多

poj 1741 树的点分治(入门)

Tree Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 18205   Accepted: 5951 Description Give a tree with n vertices,each edge has a length(positive integer less than 1001). Define dist(u,v)=The min distance between node u and v. Give an

点分治——POJ 1741

写的第一道点分治的题目,权当认识点分治了. 点分治,就是对每条过某个点的路径进行考虑,若路径不经过此点,则可以对其子树进行考虑. 具体可以看menci的blog:点分治 来看一道例题:POJ 1741 Tree 题目大意:扔给你一颗有权无根树,求有多少条路径的长度小于k: 解题思路:先找出重心,用一次dfs处理出每个点到根的距离dis,然后将dis[]排序,用O(n)的复杂度处理出"过根且长度小于等于k的路径数目",删除根节点,对于每棵子树重复上述操作. 注意要去重: 像上面这样一个图

poj 1741 楼教主男人八题之一:树分治

http://poj.org/problem?id=1741 Description Give a tree with n vertices,each edge has a length(positive integer less than 1001). Define dist(u,v)=The min distance between node u and v. Give an integer k,for every pair (u,v) of vertices is called valid

POJ 1741 树分治(点分治模板题)

POJ 1741 题意:求一棵树中点对<=k的数量. 总结:点分治,搞不太懂..大概敲了一遍 #include<iostream> #include<cstdio> #include<cstdlib> #include<algorithm> #include<cstring> #include<string> #include<cmath> #include<queue> #include<stac