首页 > 代码库 > [BZOJ1468]Tree
[BZOJ1468]Tree
[BZOJ1468]Tree
试题描述
给你一棵TREE,以及这棵树上边的距离.问有多少对点它们两者间的距离小于等于K
输入
N(n<=40000) 接下来n-1行边描述管道,按照题目中写的输入 接下来是k
输出
一行,有多少对点之间的距离小于等于k
输入示例
71 6 136 3 93 5 74 1 32 4 204 7 210
输出示例
5
数据规模及约定
见“输入”
题解
又来一道裸点分治,分别统计重心下面每一颗子树的路径长度和整棵树的路径长度,二分一下算方案数,去重。
#include <iostream>#include <cstdio>#include <algorithm>#include <cmath>#include <stack>#include <vector>#include <queue>#include <cstring>#include <string>#include <map>#include <set>using namespace std;const int BufferSize = 1 << 16;char buffer[BufferSize], *Head, *Tail;inline char Getchar() { if(Head == Tail) { int l = fread(buffer, 1, BufferSize, stdin); Tail = (Head = buffer) + l; } return *Head++;}int read() { int x = 0, f = 1; char c = getchar(); while(!isdigit(c)){ if(c == ‘-‘) f = -1; c = getchar(); } while(isdigit(c)){ x = x * 10 + c - ‘0‘; c = getchar(); } return x * f;}#define maxn 40010#define maxm 80010int n, m, K, head[maxn], next[maxm], to[maxm], dist[maxm], ans;void AddEdge(int a, int b, int c) { to[++m] = b; dist[m] = c; next[m] = head[a]; head[a] = m; swap(a, b); to[++m] = b; dist[m] = c; next[m] = head[a]; head[a] = m; return ;}bool vis[maxn];int root, size, f[maxn], siz[maxn];void getroot(int u, int fa) { siz[u] = 1; f[u] = 0; for(int e = head[u]; e; e = next[e]) if(!vis[to[e]] && to[e] != fa) { getroot(to[e], u); siz[u] += siz[to[e]]; f[u] = max(f[u], siz[to[e]]); } f[u] = max(f[u], size - siz[u]); if(f[root] > f[u]) root = u; return ;}int A[maxn], tot, B[maxn], ToT;void dfs(int u, int fa, int d) { if(d > K) return ; A[++tot] = d; for(int e = head[u]; e; e = next[e]) if(!vis[to[e]] && to[e] != fa) dfs(to[e], u, d + dist[e]); return ;}void solve(int u) {// printf("u: %d\n", u); vis[u] = 1; ToT = 0; int sum = 0; for(int e = head[u]; e; e = next[e]) if(!vis[to[e]]) { tot = 0; dfs(to[e], u, dist[e]); sort(A + 1, A + tot + 1); ans += tot;// for(int i = 1; i <= tot; i++) printf("%d ", A[i]); putchar(‘\n‘); for(int i = 1; i <= tot; i++) { int k = upper_bound(A + 1, A + tot + 1, K - A[i]) - A - 1; sum += k;// printf("%d ", k); }// puts("end"); for(int i = 1; i <= tot; i++) B[++ToT] = A[i]; }// printf("here: %d ", sum); int tmp = 0; sort(B + 1, B + ToT + 1); for(int i = 1; i <= ToT; i++) { int k = upper_bound(B + 1, B + ToT + 1, K - B[i]) - B - 1; tmp += k; }// printf("%d\n", tmp); ans += (tmp - sum >> 1); for(int e = head[u]; e; e = next[e]) if(!vis[to[e]]) { root = 0; f[0] = n + 1; size = siz[u]; getroot(to[e], u); solve(root); } return ;}int main() { n = read(); for(int i = 1; i < n; i++) { int a = read(), b = read(), c = read(); AddEdge(a, b, c); } K = read(); root = 0; f[0] = n + 1; size = n; getroot(1, 0); solve(root); printf("%d\n", ans); return 0;}
[BZOJ1468]Tree
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。