没有思路的话就看看漆子超的论文
//重心 距离 排序 统计
//http://www.2cto.com/kf/201208/149839.html#comment_iframe
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#include<algorithm>
using namespace std;
#define MAXN 10010
int N,K;
struct Node{ //邻接表
int v, w;
Node(int v_, int w_){
v= v_, w= w_;
}
};
vector<Node>son[MAXN];
int vis[MAXN]; //标记是否访问过
int num[MAXN]; //num[i]在以i为根的子树中节点的数量
int size_of_n[MAXN]; //删除n之后得到子树中子树节点的最大值
int mi,root;
void dfssize(int n, int fa) //处理子树的大小
{
num[n] = 1;
size_of_n[n] = 0;
int len=son[n].size();
for(int i=0;i<len;i++)
{
int k = son[n][i].v;
if(k != fa && !vis[k])
{
dfssize(k, n);
num[n] += num[k];
if(num[k] > size_of_n[n]) size_of_n[n] = num[k];
}
}
}
void dfsroot(int r, int n, int fa) //求重心
{
if(num[r] - num[n] > size_of_n[n]) size_of_n[n] = num[r] - num[n];
if(size_of_n[n] < mi) mi = size_of_n[n], root = n;
int len=son[n].size();
for(int i=0;i<len;i++)
{
int k = son[n][i].v;
if(k != fa && !vis[k]) dfsroot(r, k, n);
}
}
int depth[MAXN],S;
void dfs_depth(int n,int fa,int dis)
{
int i,k,len=son[n].size();
depth[++S]=dis;
for(i=0;i<len;i++){
k=son[n][i].v;
if(!vis[k]&&k!=fa) dfs_depth(k,n,dis+son[n][i].w);
}
}
/*
对depth中的距离排序后算出有多少对数字相加小于K,
dis的作用:dis==0时dfs_depth求出的距离都是以n为根并且不限制方向,
dis!=0时,假设dis为n到某个儿子的边的长度,那么求出来的所有距离都以这条边为第一步
也就是相当于限定了方向
*/
int NUM(int n,int dis){
S=0;
dfs_depth(n,-1,dis);
sort(depth+1,depth+1+S);
int i=1,j=S,ret=0;
while(i<j){
while(depth[j]+depth[i]>K&&j>i) j--;
ret+=j-i;
i++;
}
return ret;
}
int dfs_ans(int n){
mi = N;
dfssize(n, 0);
dfsroot(n, n, 0);
int SUM=0;
SUM+=NUM(root,0);
vis[root]=1;
int len=son[root].size();
for(int i=0;i<len;i++){
int k=son[root][i].v;
if(vis[k]) continue;
SUM-=NUM(k,son[root][i].w);
int temp=root;SUM+=dfs_ans(k);root=temp;
}
return SUM;
}
int main()
{
int i,j,k,u,v,l;
while(scanf("%d%d",&N,&K),N||K)
{
for(i=1;i<=N;i++){son[i].clear();}
for(i=1;i<=N-1;i++){
scanf("%d%d%d",&u,&v,&l);
son[u].push_back(Node(v,l));
son[v].push_back(Node(u,l));
}
memset(vis,0,sizeof(vis));
printf("%d\n",dfs_ans(1));
}
return 0;
}
/*
5 4
1 2 3
1 3 1
1 4 2
3 5 1
6 4
1 2 3
1 3 1
1 4 2
3 5 1
3 6 1
3 4
1 2 3
2 3 2
*/

本文介绍了一种解决特定树形结构问题的方法,通过重心分解和距离排序统计技术来高效计算树上任意两点间距离小于给定阈值K的点对数量。此算法适用于竞赛编程中的树形数据结构问题,尤其是当需要快速处理大量查询时。
758

被折叠的 条评论
为什么被折叠?



