題目大意: 給你一棵樹,問兩個點對距離<=k的點對個數;
題目分析:點分治裸題。dfs處理出每個重心(分治下)到當前子樹根節點的距離存在dis數組中,o(n)直接找出。
但要注意的是,對於dis所存的距離,只適用於兩個不同的子樹當中,所以要將位於同一個子樹中的方案數減去。
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<functional>
#include<cmath>
#include<cctype>
#include<cassert>
#include<climits>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define Forp(x) for(int p=pre[x];p;p=next[p])
#define RepD(i,n) for(int i=n;i>=0;i--)
#define MEM(a) memset(a,0,sizeof(a))
#define MEMI(a) memset(a,127,sizeof(a))
#define MEMi(a) memset(a,128,sizeof(a))
#define INF (2139062143)
#define phiF (1000000006)
#define MAXN (1000000+10)
typedef long long LL;
struct info{
int to,next,val;
bool use;
}e[100005];
int x,y,z,n,m,tot,first[100005],son[50005],f[50005],size,root,a[50005],dis[50005],k,ans;
void add(int x,int y,int z){
e[tot].to=y;
e[tot].val=z;
e[tot].next=first[x];
first[x]=tot;tot++;
}
void findroot(int u,int fa){
son[u]=1;f[u]=0;
for (int p=first[u];p!=-1;p=e[p].next){
int v=e[p].to;
if (v==fa) continue;
if (e[p].use) continue;
findroot(v,u);
f[u]=max(f[u],son[v]);
son[u]+=son[v];
}
f[u]=max(f[u],size-son[u]);
if (f[u]<f[root]) root=u;
}
void dfs(int u,int fa){
son[u]=1;
a[++a[0]]=dis[u];
for (int p=first[u];p!=-1;p=e[p].next){
int v=e[p].to;
if (!e[p].use&&v!=fa){
dis[v]=dis[u]+e[p].val;
dfs(v,u);
son[u]+=son[v];
}
}
}
int count(int u,int val){
int tmp=a[0]=0;
dis[u]=val;
dfs(u,0);
sort(a+1,a+a[0]+1);
for (int l=1,r=a[0];l<r;){
if (a[l]+a[r]<=k){
tmp+=r-l;l++;
} else r--;
}
return tmp;
}
void work(int u){
ans+=count(u,0);
for (int p=first[u];p!=-1;p=e[p].next){
if (!e[p].use){
e[p^1].use=true;
ans-=count(e[p].to,e[p].val);
f[0]=size=son[e[p].to];root=0;
findroot(e[p].to,0);
work(root);
}
}
}
char ch;
int main(){
memset(first,-1,sizeof(first));
scanf("%d%d",&n,&m);
For (i,m){
scanf("%d%d%d %c",&x,&y,&z,&ch);
add(x,y,z);
add(y,x,z);
}
scanf("%d",&k);
f[0]=size=n;
findroot(1,0);
work(root);
printf("%d",ans);
}