BZOJ 2599 [IOI2011]Race (点分治)

题目大意:

求树上长度为K的路径里,边数的最小值,$n<=10^{5}$

树分治入门题= =

为了防止出现不合法的路径进入统计,在每次选择的重心周围的节点进行统计

开一个桶,记录当前长度的路径下,边数的最小值

每次枚举当前子树内每个节点,用桶内的信息更新答案

枚举完当前子树内所有的节点之后,再把这些节点的信息推入桶内

这样就能防止出现走重边的情况了

  1 #include <cmath>
  2 #include <vector>
  3 #include <cstdio>
  4 #include <cstring>
  5 #include <algorithm>
  6 #define N1 200010
  7 #define M1 1000010
  8 #define ll long long
  9 #define inf 0x3f3f3f3f
 10 using namespace std;
 11 
 12 int gint()
 13 {
 14     int ret=0,fh=1;char c=getchar();
 15     while(c<'0'||c>'9'){if(c=='-')fh=-1;c=getchar();}
 16     while(c>='0'&&c<='9'){ret=ret*10+c-'0';c=getchar();}
 17     return ret*fh;
 18 }
 19 int n,K;
 20 struct Edge{
 21 int to[N1<<1],nxt[N1<<1],val[N1<<1],head[N1],cte;
 22 void ae(int u,int v,int w)
 23 {
 24     cte++;to[cte]=v,val[cte]=w;
 25     nxt[cte]=head[u],head[u]=cte;
 26 }
 27 }e;
 28 int ms[N1],sz[N1],use[N1],tsz,G;
 29 void gra(int u,int dad)
 30 {   
 31     sz[u]=1; ms[u]=0;
 32     for(int j=e.head[u];j;j=e.nxt[j])
 33     {
 34         if(e.to[j]==dad||use[e.to[j]]) continue;
 35         gra(e.to[j],u);
 36         sz[u]+=sz[e.to[j]]; ms[u]=max(ms[u],sz[e.to[j]]);
 37     }
 38     ms[u]=max(ms[u],tsz-sz[u]);
 39     if(ms[u]<ms[G]) G=u;
 40 }
 41 int dep[N1],dis[N1],lim;
 42 int q[N1],eq,tq[N1],et;
 43 void dfs_push(int u,int dad)
 44 {
 45     if(dis[u]>K) return;
 46     tq[++et]=u;
 47     for(int j=e.head[u];j;j=e.nxt[j])
 48     {
 49         if(e.to[j]==dad||use[e.to[j]]) continue;
 50         dep[e.to[j]]=dep[u]+1; dis[e.to[j]]=dis[u]+e.val[j];
 51         dfs_push(e.to[j],u);
 52     }
 53 }
 54 int mi[M1],ans;
 55 int calc(int u)
 56 {
 57     int i,j,x,v;
 58     mi[0]=0;
 59     for(j=e.head[u];j;j=e.nxt[j])
 60     {
 61         v=e.to[j]; if(use[v]) continue; 
 62         dis[v]=e.val[j]; dep[v]=1; dfs_push(v,u);
 63         for(i=1;i<=et;i++)
 64         {
 65             x=tq[i];
 66             ans=min(ans,dep[x]+mi[K-dis[x]]);
 67         }
 68         while(et)
 69         {
 70             x=tq[et--]; q[++eq]=dis[x];
 71             mi[dis[x]]=min(mi[dis[x]],dep[x]);
 72         }
 73     }
 74     while(eq) { x=q[eq--]; mi[x]=inf; }
 75 }
 76 void main_dfs(int u)
 77 {
 78     use[u]=1; calc(u);
 79     for(int j=e.head[u];j;j=e.nxt[j])
 80     {
 81         if(use[e.to[j]]) continue;
 82         G=0; tsz=sz[e.to[j]]; gra(e.to[j],u);
 83         main_dfs(G);
 84     }
 85 }
 86 void init()
 87 {
 88     memset(mi,0x3f,sizeof(mi));
 89     ans=inf;
 90 }
 91 
 92 int main()
 93 {
 94     //freopen("t2.in","r",stdin);
 95     int i,x,y,z; init();
 96     scanf("%d%d",&n,&K);
 97     for(i=1;i<n;i++)
 98     {
 99         x=gint(),y=gint(),z=gint(); x++,y++;
100         e.ae(x,y,z),e.ae(y,x,z);
101     }
102     ms[0]=tsz=n; G=0; gra(1,-1); gra(G,-1);
103     main_dfs(G);
104     if(ans==inf) puts("-1");
105     else printf("%d\n",ans);
106     return 0;
107 }

 

posted @ 2018-12-27 15:45  guapisolo  阅读(178)  评论(0编辑  收藏  举报