题链:
http://poj.org/problem?id=1741
题解:
树上点分治。
入门题,不多说了。
代码:
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<queue> #define MAXN 10004 using namespace std; struct EDGE{ int ent; int to[MAXN*2],nxt[MAXN*2],val[MAXN*2],head[MAXN]; void Reset(){ent=2; memset(head,0,sizeof(head));} void Adde(int u,int v,int w){ to[ent]=v; val[ent]=w; nxt[ent]=head[u]; head[u]=ent++; to[ent]=u; val[ent]=w; nxt[ent]=head[v]; head[v]=ent++; } }E; int N,K; long long ANS; int size[MAXN]; bool vis[MAXN]; void getroot(int u,int dad,int num,int &root,int &rootnum){ int maxnum=0; size[u]=0; for(int i=E.head[u];i;i=E.nxt[i]){ if(E.to[i]==dad||vis[E.to[i]]) continue; getroot(E.to[i],u,num,root,rootnum); size[u]+=size[E.to[i]]; maxnum=max(maxnum,size[E.to[i]]); } size[u]++; maxnum=max(maxnum,num-size[u]); if(maxnum<rootnum) root=u,rootnum=maxnum; } long long calc(int s,int len){ long long ret=0; static int dis[MAXN],A[MAXN],reach[MAXN],rnt,ant; static queue<int>Q; ant=0; rnt++; Q.push(s); dis[s]=len; reach[s]=rnt; while(!Q.empty()){ int u=Q.front(); Q.pop(); A[++ant]=dis[u]; for(int i=E.head[u];i;i=E.nxt[i]){ int v=E.to[i]; if(reach[v]==rnt||vis[v]) continue; dis[v]=dis[u]+E.val[i]; reach[v]=rnt; Q.push(v); } } sort(A+1,A+ant+1); int l=1,r=ant; while(l<=r){ if(A[l]+A[r]>K) r--; else ret+=r-l,l++; } return ret; } void divide(int u){ int root=u,rootnum=size[u]; getroot(u,0,size[u],root,rootnum); vis[root]=1; ANS+=calc(root,0); for(int i=E.head[root];i;i=E.nxt[i]) if(!vis[E.to[i]]) ANS-=calc(E.to[i],E.val[i]); for(int i=E.head[root];i;i=E.nxt[i]) if(!vis[E.to[i]]) divide(E.to[i]); } void read(int &x){ static int sign; static char ch; x=0; sign=1; ch=getchar(); while(ch<'0'||'9'<ch){if(ch=='-')sign=-1;ch=getchar();} while('0'<=ch&&ch<='9'){x=x*10+ch-'0';ch=getchar();} x=x*sign; } int main(){ while(1){ read(N); read(K); if(!N&&!K) break; E.Reset(); ANS=0; memset(vis,0,sizeof(vis)); for(int i=1,u,v,w;i<N;i++) read(u),read(v),read(w),E.Adde(u,v,w); size[1]=N; divide(1); printf("%lld ",ANS); } return 0; }