luoguP4178 Tree

一开始T了几发。。。

发现,出现菊花图的时候, N 2 N ^ 2 N2枚举会炸飞。。。。

(结果就直接用个桶就过了)

#include<bits/stdc++.h>
#define MAXN 80005
using namespace std;

int n,K,h[MAXN],tot,sz[MAXN],maxl[MAXN],dis[MAXN],vis[MAXN],ZX;
int dui[MAXN],js,jjs,ans[20005],sum,zzq[20005];

struct node{
	int from , to , cost , next;
}e[MAXN << 1];

void add(int x , int y , int z){
	tot++;
	e[tot].from = x;
	e[tot].to = y;
	e[tot].cost = z;
	e[tot].next = h[x];
	h[x] = tot;
}

void getsz(int now , int fa){
	sz[now] = 1;maxl[now] = 0;
	for(int i = h[now] ; i != (-1) ; i = e[i].next){
		if(e[i].to == fa || vis[e[i].to])continue;
		getsz(e[i].to , now);
		sz[now] += sz[e[i].to];
		if(sz[e[i].to] > sz[maxl[now]])maxl[now] = e[i].to;
	}
}

void getzx(int now , int fa , int yl){
	for(int i = h[now] ; i != (-1) ; i = e[i].next){
		if(e[i].to == fa || vis[e[i].to])continue;
		getzx(e[i].to , now , yl);
	}
	maxl[now] = max(sz[maxl[now]] , sz[yl] - sz[maxl[now]]);
	if(maxl[now] <= maxl[ZX])ZX = now;
}

void getdis(int now , int fa){
	for(int i = h[now] ; i != (-1) ; i = e[i].next){
		if(e[i].to == fa || vis[e[i].to])continue;
		dis[e[i].to] = dis[now] + e[i].cost;
		getdis(e[i].to , now);
	}
	if(dis[now] <= K)dui[++js] = dis[now];
}

void calc(int now){
	js = 0;
	for(int i = h[now] ; i != (-1) ; i = e[i].next){
		if(vis[e[i].to])continue;
		jjs = js;dis[e[i].to] = e[i].cost;
		getdis(e[i].to , now);
		for(int j = 1 ; j <= K ; j++){
			if(!zzq[j])continue;
			for(int k = jjs + 1 ; k <= js ; k++){
				if(j + dui[k]> K)continue;	
				ans[dui[k] + j] += zzq[j];
			}
		}
		for(int j = jjs + 1 ; j <= js ; j++)zzq[dui[j]]++;
	}
	for(int i = 1 ; i <= js ; i++)zzq[dui[i]]--;
	for(int i = 1 ; i <= js ; i++){
		if(dui[i] > K)continue;
		ans[dui[i]]++;	
	}
}

void solve(int now){
	getsz(now , now);calc(now);vis[now] = 1;
	for(int i = h[now] ; i != (-1) ; i = e[i].next){
		if(vis[e[i].to])continue;
		ZX = 0;getzx(e[i].to , now , e[i].to);
		solve(ZX);
	}
}

void init(){
	memset(h , -1 , sizeof(h));
	cin>>n;int u,v,w;maxl[0] = 9999999;
	for(int i = 1 ; i < n ; i++)cin>>u>>v>>w , add(u , v , w) , add(v , u , w);
	cin>>K;
	getsz(1 , 1);ZX = 0;
	getzx(1 , 1 , 1);
	solve(ZX);
	for(int i = 1 ; i <= K ; i++)sum = sum + ans[i];
	cout<<sum<<endl;
}

int main(){
	//freopen("P4178_1.in" , "r" , stdin);
	init();
	
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值