题目链接:http://poj.org/problem?id=1741
题目:给定一颗n个节点的数,求路径长度小于等于k的点对数。
采用分治法,不断地寻找重心,然后递归处理。
代码:
/* ***********************************************
Author :rabbit
Created Time :2014/8/2 19:27:59
File Name :1.cpp
************************************************ */
#pragma comment(linker, "/STACK:102400000,102400000")
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <sstream>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <string>
#include <time.h>
#include <math.h>
#include <queue>
#include <stack>
#include <set>
#include <map>
using namespace std;
#define INF 0x3f3f3f3f
#define eps 1e-8
#define pi acos(-1.0)
typedef long long ll;
const int maxn=10010;
int head[maxn],tol,size[maxn],vis[maxn];
int n,k,dis[maxn],num,minn;
struct Edge{
int next,to,val;
}edge[4*maxn];
void addedge(int u,int v,int w){
edge[tol].to=v;
edge[tol].next=head[u];
edge[tol].val=w;
head[u]=tol++;
}
void dfssize(int u,int pre){
size[u]=1;
for(int i=head[u];i!=-1;i=edge[i].next){
int v=edge[i].to;
if(v==pre||vis[v])continue;
dfssize(v,u);
size[u]+=size[v];
}
}
void getroot(int u,int pre,int totnum,int &root){
int maxx=totnum-size[u];
for(int i=head[u];i!=-1;i=edge[i].next){
int v=edge[i].to;
if(v==pre||vis[v])continue;
getroot(v,u,totnum,root);
maxx=max(maxx,size[v]);
}
if(maxx<minn)minn=maxx,root=u;
}
void dfsdis(int u,int d,int fa){
dis[num++]=d;
for(int i=head[u];i!=-1;i=edge[i].next){
int v=edge[i].to;
if(v==fa||vis[v])continue;
dfsdis(v,d+edge[i].val,u);
}
}
int calc(int u,int d){
int ret=0;
num=0;
dfsdis(u,d,0);
sort(dis,dis+num);
int i=0,j=num-1;
while(i<j){
while(dis[i]+dis[j]>k&&i<j)j--;
ret+=j-i;
i++;
}
return ret;
}
int ans;
void dfs(int u){//处理过u的情况
// cout<<"u="<<u<<endl;
dfssize(u,-1);
int root=u;minn=INF;
getroot(u,-1,size[u],root);
ans+=calc(root,0);
vis[root]=1;
for(int i=head[root];i!=-1;i=edge[i].next){
int v=edge[i].to;
if(vis[v])continue;
ans-=calc(v,edge[i].val);
dfs(v);
}
}
int main()
{
//freopen("data.in","r",stdin);
//freopen("data.out","w",stdout);
while(cin>>n>>k){
if(n==0&&k==0)break;
memset(head,-1,sizeof(head));tol=0;
memset(vis,0,sizeof(vis));
ans=0;
for(int i=1;i<n;i++){
int a,b,c;
cin>>a>>b>>c;
addedge(a,b,c);
addedge(b,a,c);
}
dfs(1);
cout<<ans<<endl;
}
return 0;
}