Tree
对于每一条连到当前根的比k小的边edge,找比k-edge小的,不难想到树状数组。
比较坑的是树状数组一定要定义局部变量,不然会奇妙WA哈哈。
看一下代码:
#include<bits/stdc++.h>
using namespace std;
int n,k;
const int maxn=100000;
int beg[maxn],nex[maxn],to[maxn],w[maxn],e;
void add(int x,int y,int z){
e++;nex[e]=beg[x];
beg[x]=e;to[e]=y;w[e]=z;
}
#define inf 1e9
int rt,mx,size;
int sz[maxn],son[maxn],vis[maxn];
inline void getrt(int x,int fa){
sz[x]=1,son[x]=0;
for(int i=beg[x];i;i=nex[i]){
int t=to[i];
if(vis[t]||t==fa)continue;
getrt(t,x);
sz[x]+=sz[t];
if(son[x]<sz[t])son[x]=sz[t];
}
if(son[x]<size-sz[x])son[x]=size-sz[x];
if(mx>son[x])mx=son[x],rt=x;
}
int q[maxn],ans,top;
inline void stk(int x,int fa,int val){
if(val>k)return;
if(val==k){
ans++;
return;
}
q[++top]=val;
for(int i=beg[x];i;i=nex[i]){
int t=to[i];
if(vis[t]||t==fa)continue;
stk(t,x,val+w[i]);
}
}
inline int lowbit(int x){
return x&(-x);
}
inline void divide(int x){
//printf("%d\n",x);
vis[x]=1;
int c[k+10]={0};
for(int i=beg[x];i;i=nex[i]){
int t=to[i];
if(vis[t])continue;
top=0;
stk(t,x,w[i]);
ans+=top;
//printf("%d %d %d %d ",t,x,top,ans);
for(int j=1;j<=top;j++){
int tmp=k-q[j];
while(tmp){
ans+=c[tmp];
tmp-=lowbit(tmp);
}
}
//printf("%d\n",ans);
for(int j=1;j<=top;j++){
int tmp=q[j];
while(tmp<=k){
c[tmp]++;
tmp+=lowbit(tmp);
}
}
mx=inf,size=sz[t],rt=0;
getrt(t,x);
divide(rt);
}
//printf("%d %d\n",qwq,x);
}
int main(){
cin>>n;
int x,y,z;
for(int i=1;i<n;i++){
scanf("%d%d%d",&x,&y,&z);
add(x,y,z);add(y,x,z);
}
cin>>k;
mx=inf,rt=0,size=n;
getrt(1,0);
divide(rt);
printf("%d\n",ans);
return 0;
}
努力想想的我一遍A了。