男人八题,关键就是找树的质心,每次处理一颗子树重新找质心(DP),用一种很暴力的方法,将树的深度限制在了log(n),这道题目的极端数据就是退化成一个链表的树,目测10000个点。然后统计合法点对,即可,统计方法很多,平衡树,排序扫描等等。
Tree
Time Limit: 1000MS | Memory Limit: 30000K | |
Total Submissions: 7598 | Accepted: 2215 |
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
#include<iostream>
#include<cstring>
#include<algorithm>
#include<string>
#include<cstdio>
#include<vector>
using namespace std;
#define INF 0x3f3f3f3
int ans;
int n,k;
int tot[20010];
int mins,total,root;
int dis[20010],p;
int vis[20010];
int head[20010],en;
int cnt[20010];
struct edges
{
int to,next,dis;
}edge[22000];
void add(int u,int v,int d)
{
edge[en].to=v;
edge[en].dis=d;
edge[en].next=head[u];
head[u]=en++;
edge[en].to=u;
edge[en].dis=d;
edge[en].next=head[v];
head[v]=en++;
}
void dfs(int u,int f)
{
tot[u]=1;
int mxs=0;
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].to;
if(v==f||vis[v]) continue;
dfs(v,u);
tot[u]+=tot[v];
mxs=max(mxs,tot[v]);
}
if(mxs<total-tot[u])
mxs=total-tot[u];
if(mxs<mins)
mins=mxs,root=u;
}
void getdis(int u,int f,int distances)
{
dis[p++]=distances;
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].to;
if(v==f||vis[v]) continue;
getdis(v,u,distances+edge[i].dis);
}
}
int counts(int u,int distances)
{
int ret=0;
p=0;
getdis(u,0,distances);
sort(dis,dis+p);
int l=0,r=p-1;
while(l<r)
{
if(dis[l]+dis[r]<=k)
ret+=(r-l),l++;
else
r--;
}
return ret;
}
void func(int u)
{
mins=INF,mins=INF,total=tot[u] ? tot[u]:n;
dfs(u,0);
u=root;
vis[u]=1;
cnt[u]=0;
cnt[u]+=counts(u,0);
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].to;
if(vis[v]) continue;
cnt[u]-=counts(v,edge[i].dis);
func(v);
}
}
int main()
{
int u,v,d;
while(scanf("%d%d",&n,&k))
{
if(n==0&&k==0) break;
memset(head,-1,sizeof(head));en=0;
for(int i=1;i<n;i++)
{
scanf("%d%d%d",&u,&v,&d);
add(u,v,d);
}
ans=0;
memset(vis,0,sizeof(vis));tot[1]=0;
func(1);
for(int i=1;i<=n;i++) ans+=cnt[i];
cout<<ans<<endl;
}
return 0;
}