Poj-1741 Tree(树的点分治)

来源:互联网 发布:多普达软件下载 编辑:程序博客网 时间:2024/06/05 00:18

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 41 2 31 3 11 4 23 5 10 0

Sample Output

8

Source

LouTiancheng@POJ


题意:给定一颗带边权的树,问数上距离不超过k的不同点对有多少个。

分析:树的点分治,所有树上的路径要么经过根节点要么属于一颗子树,我们处理出经过根节点的值,然后对所有子树递归处理,每次选择重心作为根的话最多走log(n)层,每层log(n)*n的排序复杂度,总复杂度n*log(n)*log(n)。

#include<iostream>#include<string>#include<algorithm>#include<cstdlib>#include<cstdio>#include<set>#include<map>#include<vector>#include<cstring>#include<stack>#include<cmath>#include<queue>#define INF 0x3f3f3f3f#define eps 1e-9  #define MOD 1000000007 #define MAXN 10005using namespace std;typedef long long ll;typedef pair<int,int> pii;vector<pii> G[MAXN];vector<int> b;int n,k,ans,root,size[MAXN];bool jud[MAXN];int dfs(int u,int fa,int tot){bool flag = true;size[u] = 1;for(int i = 0;i < G[u].size();i++){pii vv = G[u][i]; if(vv.first != fa && !jud[vv.first]) { int v = vv.first; int tmp = dfs(v,u,tot); if(tmp) return tmp; size[u] += size[v]; if(size[v] > tot/2 ) flag = false; }}if(tot - size[u] > tot/2) flag = false;return flag ? u : 0;}int got_size(int u,int fa){int num = 1;for(int i = 0;i < G[u].size();i++){pii vv = G[u][i];if(vv.first != fa && !jud[vv.first]) num += got_size(vv.first,u);}return num;}void dfs2(int u,int fa,int deep){b.push_back(deep);for(int i = 0;i < G[u].size();i++){pii vv = G[u][i]; if(vv.first != fa && !jud[vv.first]) dfs2(vv.first,u,deep+vv.second);}}void deal(int u,int deep,int x){b.clear();dfs2(u,-1,deep);sort(b.begin(),b.end());int tot = 0,sum = b.size(),r = -1;for(int i = sum-1;i;i--){while(b[i] + b[r+1] <= k && r+1 < i) r++;if(i == r) r--;tot += r+1; }ans += tot*x;}void calc(int u){deal(u,0,1);jud[u] = true;for(int i = 0;i < G[u].size();i++){pii vv = G[u][i]; if(!jud[vv.first])  { int v = vv.first;  deal(v,vv.second,-1); int root = dfs(v,u,got_size(v,u)); calc(root); }}}int main(){while(scanf("%d%d",&n,&k) && n+k){ans = 0;memset(jud,0,sizeof(jud));for(int i = 1;i <= n;i++) G[i].clear();for(int i = 1;i < n;i++){int u,v,val;scanf("%d%d%d",&u,&v,&val);G[u].push_back(make_pair(v,val));G[v].push_back(make_pair(u,val));} root = dfs(1,0,n);calc(root);cout<<ans<<endl;}}



0 0
原创粉丝点击