BZOJ 2599 Race(树分治)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2599

题意:给一棵树,每条边有权.求一条路径,权值和等于K,且边的数量最小.

题意:每次找到当前树的重心作为树根,查找通过当前树根的路径。

  1 #include<algorithm>
  2 #include<cstdio>
  3 #include<cmath>
  4 #include<cstring>
  5 #include<iostream>
  6 #include<ctime>
  7 int tot,go[1000005],next[1000005],first[1000005],val[1000005];
  8 int size[1000005],F[1000005],cnt[1000005],a[1000005],root,n,K,vis[1000005];
  9 int dis[1000005],ans,sz,h[1000005],sum;
 10 long long sx;
 11 int read(){
 12     char ch=getchar();int t=0,f=1;
 13     while (ch<'0'||ch>'9') {
 14         if (ch=='-') f=-1;
 15         ch=getchar();
 16     }
 17     while ('0'<=ch&&ch<='9'){
 18         t=t*10+ch-'0';
 19         ch=getchar();
 20     }
 21     return t*f;
 22 }
 23 void insert(int x,int y,int z){
 24     tot++;
 25     go[tot]=y;
 26     next[tot]=first[x];
 27     first[x]=tot;
 28     val[tot]=z;
 29 }
 30 void add(int x,int y,int z){
 31     insert(x,y,z);
 32     insert(y,x,z);
 33 }
 34 void findroot(int x,int fa){
 35     size[x]=1;F[x]=0;
 36     for (int i=first[x];i;i=next[i]){
 37         int pur=go[i];
 38         if (pur==fa||vis[pur]) continue;
 39         findroot(pur,x);
 40         size[x]+=size[pur];
 41         F[x]=std::max(F[x],size[pur]);
 42     }
 43     F[x]=std::max(F[x],sum-size[x]);
 44     if (F[root]>F[x]) root=x;
 45 }
 46 void dfs1(int x,int fa){
 47     sx++;
 48     if (dis[x]>K) return;
 49     if (h[K-dis[x]]==sz) ans=std::min(ans,a[K-dis[x]]+cnt[x]);
 50     for (int i=first[x];i;i=next[i]){
 51         int pur=go[i];
 52         if (pur==fa||vis[pur]) continue;
 53         cnt[pur]=cnt[x]+1;
 54         dis[pur]=dis[x]+val[i];
 55         dfs1(pur,x);
 56     }
 57 }
 58 void dfs2(int x,int fa){
 59     if (dis[x]>K) return;
 60     if (h[dis[x]]!=sz) h[dis[x]]=sz,a[dis[x]]=cnt[x];
 61     else a[dis[x]]=std::min(a[dis[x]],cnt[x]);
 62     for (int i=first[x];i;i=next[i]){
 63         int pur=go[i];
 64         if (pur==fa||vis[pur]) continue;
 65         dfs2(pur,x);
 66     }
 67 }
 68 int find(int x,int fa){
 69     int all=1;
 70     for (int i=first[x];i;i=next[i]){
 71         int pur=go[i];
 72         if (pur==fa||vis[pur]) continue;
 73         all+=find(pur,x);
 74     }
 75     return all;
 76 }
 77 void query(int x){
 78     h[0]=++sz;
 79     a[0]=0;
 80     vis[x]=1;
 81     for (int i=first[x];i;i=next[i]){
 82         int pur=go[i];
 83         if (vis[pur]) continue;
 84         dis[pur]=val[i];
 85         cnt[pur]=1;
 86         dfs1(pur,x);
 87         dfs2(pur,x);
 88     }
 89     for (int i=first[x];i;i=next[i]){
 90         int pur=go[i];
 91         if (vis[pur]) continue;
 92         root=0;
 93         sum=find(pur,0);
 94         findroot(pur,0);
 95         query(root);
 96     }
 97 }
 98 int main(){
 99     n=read();K=read();
100     for (int i=1;i<n;i++){
101         int x,y,z;
102         x=read();
103         y=read();
104         z=read();
105         x++;y++;
106         add(x,y,z);
107     }
108     root=0;
109     F[0]=n+1;
110     ans=n;
111     sum=n;
112     findroot(1,0);
113     query(root);
114     if (ans==n) ans=-1;
115     printf("%d\n",ans);
116 }

 

posted @ 2016-05-28 17:09  GFY  阅读(162)  评论(0编辑  收藏  举报