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
",i);return 0;}
62     puts("-1");
63     return 0;
64 }
bzoj2599
原文地址:https://www.cnblogs.com/gjghfd/p/6686284.html