bzoj2599 [ IOI2011 ] -- 点分治
令ans[i]表示权值和等于k的路径条数,然后点分治就可以了。
具体看代码。
代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<vector> 6 using namespace std; 7 #define N 200010 8 #define INF 2147483647 9 inline int Min(int x,int y){return x<y?x:y;} 10 inline int Max(int x,int y){return x<y?y:x;} 11 vector<int>g[N]; 12 vector<int>w[N]; 13 struct Node{ 14 int x,y; 15 Node(){} 16 Node(int x,int y):x(x),y(y){} 17 }a[N]; 18 int i,j,k,n,m,f[N],s[N],Sum,Rt,Ans[N],x,y,z,l; 19 bool b[N]; 20 inline void Add(int x,int y,int z){g[x].push_back(y);w[x].push_back(z);} 21 inline void Get_root(int x,int y){ 22 s[x]=1;f[x]=0; 23 for(int i=0;i<g[x].size();i++) 24 if(!b[g[x][i]]&&g[x][i]!=y){ 25 Get_root(g[x][i],x); 26 s[x]+=s[g[x][i]]; 27 f[x]=Max(f[x],s[g[x][i]]); 28 } 29 f[x]=Max(f[x],Sum-s[x]); 30 if(f[x]<f[Rt])Rt=x; 31 } 32 inline void Dfs(int x,int y,int z,int Sum){ 33 a[++l]=Node(z,Sum); 34 for(int i=0;i<g[x].size();i++) 35 if(!b[g[x][i]]&&g[x][i]!=y)Dfs(g[x][i],x,z+w[x][i],Sum+1); 36 } 37 inline bool Cmp(Node a,Node b){return a.x<b.x;} 38 inline void Calc(int x,int y,int z){ 39 l=0;if(y==1)Dfs(x,0,z,0);else Dfs(x,0,z,1); 40 sort(a+1,a+l+1,Cmp); 41 for(int i=1;i<=l;i++){ 42 while(a[l].x+a[i].x>k&&l>i)l--; 43 for(int p=l;a[p].x+a[i].x==k;p--)Ans[a[p].y+a[i].y]+=y; 44 } 45 } 46 inline void Solve(int x){ 47 b[x]=1;Calc(x,1,0); 48 for(int i=0;i<g[x].size();i++) 49 if(!b[g[x][i]]){ 50 Calc(g[x][i],-1,w[x][i]); 51 Sum=s[g[x][i]];f[Rt=0]=n+1;Get_root(g[x][i],0); 52 Solve(Rt); 53 } 54 } 55 int main(){ 56 scanf("%d%d",&n,&k); 57 for(i=1;i<n;i++)scanf("%d%d%d",&x,&y,&z),Add(x+1,y+1,z),Add(y+1,x+1,z); 58 Sum=n;f[Rt=0]=n+1;Get_root(1,0); 59 Solve(Rt); 60 for(i=1;i<=n;i++) 61 if(Ans[i]>0){printf("%d\n",i);return 0;} 62 puts("-1"); 63 return 0; 64 }