POJ 1741 Tree(点分治)

点分治...模板题吧..只要理解了,实现并不难,随便搞搞...

 ---------------------------------------------------------------------

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<vector>
 
#define rep(i, n) for(int i = 0; i < n; ++i)
#define REP(x) for(edge* e = head[x]; e; e = e->next)
#define clr(x, c) memset(x, c, sizeof(x))
 
using namespace std;
 
const int maxn = 10000 + 5;
const int inf = 0x7fffffff;
 
int n, K;
 
struct edge {
int to, dist;
edge* next;
};
 
edge* pt;
edge* head[maxn];
edge EDGE[maxn << 1];
 
inline void init() {
pt = EDGE;
clr(head, 0);
}
 
inline void add(int u, int v, int d) {
pt->to = v;
pt->dist = d;
pt->next = head[u];
head[u] = pt++;
}
 
inline void add_edge(int u, int v, int d) {
add(u, v, d);
add(v, u, d);
}
 
int size[maxn];
bool vis[maxn];
 
int dp(int x, int fa) {
size[x] = 1;
REP(x) if(!vis[e->to] && e->to != fa)
size[x] += dp(e->to, x);
return size[x];
}
 
int root, Min;
int node_num;
 
void dfs(int x, int fa) {
int Max = node_num - size[x];
REP(x) if(fa != e->to && !vis[e->to]) {
Max = max(Max, size[e->to]);
dfs(e->to, x);
}
if(Max < Min)
   root = x, Min = Max;
}
 
void Dfs(int x) {
Min = inf;
node_num = dp(x, -1);
dfs(x, -1);
}
 
vector<int> d;
 
void DFS(int x, int fa, int dist) {
d.push_back(dist);
REP(x) if(!vis[e->to] && fa != e->to)
DFS(e->to, x, dist + e->dist);
}
 
int Count(int x, int dist) {
d.clear();
DFS(x, -1, dist);
sort(d.begin(), d.end());
int ans = 0, l = 0, r = d.size() - 1;
while(l < r) {
while(d[l] + d[r] > K && l < r) r--;
ans += r - l;
l++;
}
return ans;
}
 
int ANS;
 
void COUNT(int x) {
Dfs(x);
vis[root] = 1;
ANS += Count(root, 0);
REP(root) if(!vis[e->to])
   ANS -= Count(e->to, e->dist), COUNT(e->to);
}
 
inline void COUNT_init() {
ANS = 0;
clr(vis, 0);
}
 
void work() {
COUNT_init();
COUNT(0);
cout << ANS << " ";
}
 
void Read() {
int u, v, d;
rep(i, n - 1)
   scanf("%d%d%d", &u, &v, &d), add_edge(u - 1, v - 1, d);
}
 
int main() {
// freopen("test.in", "r", stdin);
while(cin >> n >> K) {
if(!n && !K) break;
init();
Read();
work();
}
return 0;
}

  

---------------------------------------------------------------------- 

Tree
Time Limit: 1000MSMemory Limit: 30000K
Total Submissions: 12802Accepted: 4079

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) not exceed k. 
Write a program that will count how many pairs which are valid for a given tree. 

Input

The input contains several test cases. The first line of each test case contains two integers n, k. (n<=10000) The following n-1 lines each contains three integers u,v,l, which means there is an edge between node u and v of length l. 
The last test case is followed by two zeros. 

Output

For each test case output the answer on a single line.

Sample Input

5 4 1 2 3 1 3 1 1 4 2 3 5 1 0 0 

Sample Output

8

Source

原文地址:https://www.cnblogs.com/JSZX11556/p/4509586.html