记录编号 363657 评测结果 AAAAAAAAAA
题目名称 [POJ1741][男人八题]树上的点对 最终得分 100
用户昵称 GravatarFoolMike 是否通过 通过
代码语言 C++ 运行时间 0.789 s
提交时间 2017-01-12 14:00:26 内存使用 4.20 MiB
显示代码纯文本
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=1e5+10;
struct edge{
	int f,t,l;
	edge(int F=0,int T=0,int L=0){
		f=F;t=T;l=L;
	}
}w[N];
int n,k,head[N],tail[N],next[N],cnt;
void add(int f,int t,int l){
	w[++cnt]=edge(f,t,l);
	if (!head[f]) head[f]=tail[f]=cnt;
		else tail[f]=next[tail[f]]=cnt;
}
int s[N],h[N],dis[N],big[N],root,size,sum;
bool vis[N];
void getroot(int x,int fa){
	s[x]=1;big[x]=0;
	for (int i=head[x];i;i=next[i]){
		int v=w[i].t;
		if (vis[v]||v==fa) continue;
		getroot(v,x);
		s[x]+=s[v];
		big[x]=max(big[x],s[v]);
	}
	if (big[x]<=size/2&&s[x]>=size/2) root=x;
}
void geth(int x,int fa){
	h[++sum]=dis[x];
	for (int i=head[x];i;i=next[i]){
		int v=w[i].t;
		if (vis[v]||v==fa) continue;
		dis[v]=dis[x]+w[i].l;
		geth(v,x);
	}
}
int calc(int x,int H){
	dis[x]=H;sum=0;
	geth(x,0);
	sort(h+1,h+sum+1);
	int ans=0;
	for (int l=1,r=sum;l<r;l++){
		while (l<r&&h[l]+h[r]>k) r--;
		ans+=r-l;
	}
	return ans;
}
int DC(int x){
	int ans=calc(x,0);
	vis[x]=1;
	getroot(x,0);
	for (int i=head[x];i;i=next[i]){
		int u=w[i].t;
		if (vis[u]) continue;
		ans-=calc(u,w[i].l);
		root=0;size=s[u];getroot(u,0);
		ans+=DC(root);
	}
	return ans;
}
int main()
{
	freopen("poj1741_tree.in","r",stdin);
	freopen("poj1741_tree.out","w",stdout);
	while (1){
		scanf("%d%d",&n,&k);
		if (!n&&!k) break;
		for (int i=1;i<=n;i++) head[i]=tail[i]=vis[i]=0;
		for (int i=1;i<=cnt;i++) next[i]=0;
		cnt=0;
		for (int i=1;i<n;i++){
			int f,t,l;
			scanf("%d%d%d",&f,&t,&l);
			add(f,t,l);add(t,f,l);
		}
		root=0;size=n;getroot(1,0);
		printf("%d\n",DC(root));
	}
	return 0;
}