bzoj2599 [ IOI2011 ] -- 点分治

来源:互联网 发布:重庆优化 编辑:程序博客网 时间:2024/06/05 20:24
令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 }
bzoj2599

 

原创粉丝点击