Tree
Time Limit: 1000MS | Memory Limit: 30000K | |
Total Submissions: 28490 | Accepted: 9502 |
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.
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.
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
题解:
这篇东西点分治讲的很好(可惜那边的代码这题过不去QWQ)
点分治模板题。
用点分治算出经过当前重心的满足条件对数,然后删除每个儿子节点的满足条件去重。
时间复杂度nlog^2n
代码(前面也过不去,大概是清空数组时时间太多了,把数组改小卡过去了):
#include <iostream>
#include <fstream>
#include <cstdio>
#include <cmath>
#include <map>
#include <set>
#include <bitset>
#include <ctime>
#include <cstring>
#include <algorithm>
#include <stack>
#include <queue>
#include <vector>
#include <list>
using namespace std;
int tot,n,m,S,MX,summar,root,ans,vis[10001],e[20001],nexr[20001],head[20001],sim[10001],dis[10001],jia[20001],mxson[10001];
void build(int t,int k,int s){
tot++;
e[tot]=k;jia[tot]=s;
nexr[tot]=head[t];head[t]=tot;
}
void getroot(int x,int fa){
int i;
sim[x]=1;mxson[x]=0;
for(i=head[x];i;i=nexr[i]){
if(e[i]==fa||vis[e[i]])continue;
getroot(e[i],x);
sim[x]+=sim[e[i]];
mxson[x]=max(mxson[x],sim[e[i]]);
}
mxson[x]=max(mxson[x],S-sim[x]);
if(mxson[x]<MX){
root=x;
MX=mxson[x];
}
}
void getdis(int x,int fa,int dist){
dis[++summar]=dist;
int i;
for(i=head[x];i;i=nexr[i]){
if(vis[e[i]]||e[i]==fa)continue;
getdis(e[i],x,dist+jia[i]);
}
}
int consolate(int x,int len){
memset(dis,0,sizeof(dis));
summar=0;
getdis(x,0,len);
sort(dis+1,dis+summar+1);
int l=1,r=summar,sum=0;
while(l<=r){
if(dis[l]+dis[r]<=m){
sum+=r-l;
l++;
}
else r--;
}
return sum;
}
void divide(int x){
ans+=consolate(x,0);
vis[x]=1;
int i;
for(i=head[x];i;i=nexr[i]){
if(vis[e[i]])continue;
ans-=consolate(e[i],jia[i]);
S=sim[e[i]];root=0;
MX=n+1;getroot(e[i],0);
divide(root);
}
}
int main(){
int i,t,k,s;
while(1){
scanf("%d%d",&n,&m);
if(n==0&&m==0)return 0;
tot=0;
memset(head,0,sizeof(head));
for(i=1;i<n;i++){
scanf("%d%d%d",&t,&k,&s);
build(t,k,s);build(k,t,s);
}
S=n;MX=n+1;ans=0;
memset(vis,0,sizeof(vis));
getroot(1,0);
divide(root);
printf("%d\n",ans);
}
}