Test instructions
Given a tree with the right edge, the number of disordered pairs of points not exceeding K on the tree is obtained.
Solution
Tree divide and cure practiced hand problem ...
Three kinds of divide and conquer, point divide and conquer, divide and conquer, chain divide and cure, all can.
Point Division should not be difficult to write, but do not bother to write a balanced tree, the relative good to write the side of the division. (because it is necessary to use a balance tree to divide the senses ...)
Point division is to choose the center of gravity when the root node, and then count the path through the root node. Edge Division is a direct search for a cut can make both sides of the tree as far as possible to balance the edge, the number of paths through the edge.
When the specific writing, the distance between the two sides were thrown into two vectors, and then two points can be. or directly based on monotonic linear scanning.
When a linear scan is in the statistical path, the complexity is O (Nlogn), which seems to be faster than the O (nlog2n) of the point division. However, because of the constant limit, it is actually very slow.
In the worst case, the recursion depth will reach O (n) (such as a daisy-shaped tree), so the worst complexity can be improved by inserting a white point. By inserting white dots at the point to the son's path, the number of sons of each point is reduced to <=2, so that each point has no more than 3 degrees, and the maximum recursion depth is O (logn).
Since the built tree resembles a line segment tree, the size of the tree is enlarged by at most one times, just a constant problem. The total complexity is still O (Nlogn).
The first time to write a tree division, writing more ugly ... Let's see.
1#include <cstdio>2#include <cstring>3#include <algorithm>4#include <vector>5#include <queue>6 using namespacestd;7 Const intmaxn=50010;8 structedge{9 intTo,w,prev;Ten BOOLVis; One}e[maxn<<1]; A voidPredfs (int,int);//pretreatment, adding white point - voidAddedge (int,int,int); - voidSolveint); the voidDfsint,int);//Count Size - voidDFS1 (int,int,int&);//looking for a side to divide - voidDFS2 (int,int,int,vector<int>&);//Calculation Distance - intn,k,last[maxn],len,size[maxn],siz,tmp,ans,du[maxn],x,y,z; + BOOLwhite[maxn]={false}; -vector<int>b; +vector<pair<int,int> >G[MAXN]; A intMain () { at #defineMINE - #ifdef MINE -Freopen ("poj1741_tree.in","R", stdin); -Freopen ("Poj1741_tree.out","W", stdout); - #endif - while(SCANF ("%d%d", &n,&k) = =2&&n&&k) { inmemset (last,-1,sizeof(last)); -memset (White,0,sizeof(white)); toMemset (Du,0,sizeof(du)); + for(intI=1; i<=20000; i++) g[i].clear (); -len=0; the for(intI=1; i<n;i++){ *scanf"%d%d%d",&x,&y,&z); $ G[x].push_back (Make_pair (y,z));Panax Notoginseng G[y].push_back (Make_pair (x,z)); - } theans=0; +Predfs (1,0); ASolve1); theprintf"%d\n", ans); + } - #ifndef MINE $printf"\ n--------------------done--------------------\ n"); $ for(;;); - #endif - return 0; the } - voidPredfs (intXintp) {Wuyi intCnt=g[x].size (); the for(intI=0; i<cnt;i++)if(g[x][i].first!=p) Predfs (g[x][i].first,x); -queue<pair<int,int> >Q; Wu for(intI=0; i<cnt;i++)if(g[x][i].first!=p) Q.push (G[x][i]); -Cnt=q.size (); About while(cnt>2){ $pair<int,int>a=Q.front (); Q.pop (); -pair<int,int>b=Q.front (); Q.pop (); - inty=++N; -white[y]=true; A Addedge (y,a.first,a.second); + Addedge (a.first,y,a.second); the Addedge (y,b.first,b.second); - Addedge (b.first,y,b.second); $Q.push (Make_pair (Y,0)); thecnt--; the } the while(!Q.empty ()) { the Addedge (X,q.front (). First,q.front (). second); - Addedge (Q.front (). First,x,q.front (). second); in Q.pop (); the } the } About voidAddedge (intXintYintz) { thee[len].to=y; thee[len].w=Z; thee[len].prev=Last[x]; +last[x]=len++; - } the voidSolveintx) {BayiTmp=~ (1<< to); the intid=-1; theDFS (x,0); -siz=Size[x]; -DFS1 (x,0, id); the if(id==-1)return; thee[id].vis=e[id^1].vis=true; the solve (e[id].to); theSolve (e[id^1].to); - a.clear (); the b.clear (); theDFS2 (E[id].to,0,0, a); theDFS2 (e[id^1].to,0,0, b);94 sort (A.begin (), A.end ()); the sort (B.begin (), B.end ()); the intCnta=a.size (), cntb=b.size (); the for(intI=0, j=cntb-1; i<cnta;i++){98 while(~j&&k-a[i]-e[id].w<b[j]) j--; Aboutans+=j+1; - }101e[id].vis=e[id^1].vis=false;102 }103 voidDfsintXintp) {104size[x]=1; the for(inti=last[x];i!=-1; i=e[i].prev)if(e[i].to!=p&&!E[i].vis) {106 DFS (e[i].to,x);107size[x]+=size[e[i].to];108 }109 } the voidDFS1 (intXintPint&ID) {111 for(inti=last[x];i!=-1; i=e[i].prev)if(e[i].to!=p&&!E[i].vis) { the if(ABS (size[e[i].to]-(siz-size[e[i].to)) <tmp) {113Id=i; theTmp=abs (size[e[i].to]-(siz-size[e[i].to])); the } the DFS1 (e[i].to,x,id);117 }118 }119 voidDFS2 (intXintPintd,vector<int>&a) { - if(!white[x]) a.push_back (d);121 for(inti=last[x];i!=-1; i=e[i].prev)if(E[i].to!=p&&!e[i].vis) DFS2 (e[i].to,x,d+e[i].w,a);122}View Code
PostScript
The first tree divided, so dedicated to the side of the divided treatment ...
Bullish multi-god Ben with the point of treatment, I feel really wonderful ...
The end and the beginning, there is always one waiting for you.
A point-pair puzzle on a tree