难点在于要想办法把问题转化成支持减法的
#include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<algorithm> #include<iostream> #define maxn 100010 using namespace std; int to[maxn],head[maxn],dep[maxn],next[maxn],len[maxn],size[maxn]; int st[maxn],fa[maxn]; bool vis[maxn]; int n,m,num,ans,k,root,top; char s[5]; void addedge(int x,int y,int z) { num++;to[num]=y;len[num]=z;next[num]=head[x];head[x]=num; } void get_root(int x,int Size,int &cg)//在树里找重心 { bool flag=1; size[x]=1; for (int p=head[x];p;p=next[p]) if (!vis[to[p]] && to[p]!=fa[x]) { fa[to[p]]=x; get_root(to[p],Size,cg); if (size[to[p]]>Size/2) flag=0; size[x]+=size[to[p]]; } if (Size-size[x]>Size/2) flag=0; if (flag) cg=x; } void dfs1(int x,int d)//建立树结构 { dep[x]=d; for (int p=head[x];p;p=next[p]) if (!vis[to[p]] && to[p]!=fa[x]) fa[to[p]]=x,dfs1(to[p],d+len[p]); } void dfs2(int x) { st[++top]=dep[x]; for (int p=head[x];p;p=next[p]) if (!vis[to[p]] && to[p]!=fa[x]) dfs2(to[p]); } int calc(int root) { int ans=0; top=0; dfs2(root); sort(st+1,st+top+1); for (int i=1,j=top;i<=j;i++) { while (j>i && st[i]+st[j]>k) j--; ans+=j-i; } return ans; } void solve(int x,int Size)//要分治的根节点和分治的树的大小 { int cg; fa[x]=0; get_root(x,Size,cg); size[fa[cg]]=Size-size[cg]; fa[cg]=0;vis[cg]=1; dfs1(cg,0); ans+=calc(cg); for (int p=head[cg];p;p=next[p]) if (!vis[to[p]]) ans-=calc(to[p]); for (int p=head[cg];p;p=next[p]) if (!vis[to[p]]) solve(to[p],size[to[p]]); } int main() { scanf("%d%d",&n,&m); for (int i=1;i<n;i++) { int x,y,z; scanf("%d%d%d",&x,&y,&z); addedge(x,y,z);addedge(y,x,z); scanf("%s",s); } scanf("%d",&k); solve(1,n); printf("%d\n",ans); return 0; }