HDU多校2020 第十场 1005/6881-Tree Cutting(点分治

题意:http://acm.hdu.edu.cn/showproblem.php?pid=6881

求直径为k的树最多包多少点

思路:

一开始直接上了动态点分治,甚至傻乎乎得上了树状数组,其实搞个数组计个前缀和就够了,但是又开了主席树空间不够,也是TLE,还卡栈空间

看了std发现可以从外到内直接统计贡献,很类似树DP,分成在外面的和在里面两种,边有点不太一样,我还一度认为是和点一样的调了好久,这题似乎读入不多,读入挂没什么用

  1 unordered_map<ll,int>mp;
  2 int k,ek;
  3 int dep[N],Dep[N],id[N];
  4 int max_dep[N];
  5 int selfcnt[N],soncnt[N];
  6 int ansnode[N],ansedge[N];
  7 class TREEDiv
  8 {
  9 public:
 10     bool vis[N];
 11     int sz[N],stk[N],anc[N],top,MX;
 12     int rt,respart;
 13     void Init(int n)
 14     {
 15         for(int i=0;i<=n;++i)vis[i]=0;
 16     }
 17     void get_gravity(int u,int f,int S)
 18     {
 19         sz[u]=1;
 20         int max_part=0;
 21         for(int i=head[u];i;i=edge[i].next)
 22         {
 23             int to=edge[i].to;
 24             if(to==f||vis[to])continue;
 25             get_gravity(to,u,S);
 26             sz[u]+=sz[to];
 27             max_part=max(max_part,sz[to]);
 28         }
 29         max_part=max(max_part,S-sz[u]);
 30         if(max_part<respart)
 31         {
 32             respart=max_part;
 33             rt=u;
 34         }
 35     }
 36     void get_self(int u,int f,int depth)
 37     {
 38         max_dep[rt]=max(max_dep[rt],depth);
 39         dep[u]=depth;
 40         selfcnt[depth]++;
 41         sz[u]=1;
 42         for(int i=head[u];i;i=edge[i].next)
 43         {
 44             int to=edge[i].to;
 45             if(to==f||vis[to])continue;
 46             get_self(to,u,depth+1);
 47             sz[u]+=sz[to];
 48         }
 49     }
 50     void get_son(int u,int f)
 51     {
 52         MX=max(MX,dep[u]);
 53         soncnt[dep[u]]++;
 54         stk[++top]=u;
 55         anc[u]=f;
 56         for(int i=head[u];i;i=edge[i].next)
 57         {
 58             int to=edge[i].to;
 59             if(to==f||vis[to])continue;
 60             get_son(to,u);
 61         }
 62     }
 63     void workson(int u,int f)
 64     {
 65         MX=0;top=0;
 66         get_son(u,f);
 67         for(int i=2;i<=MX;++i)soncnt[i]+=soncnt[i-1];
 68         ansedge[Dep[u]>Dep[f]?id[u]:id[f]]+=soncnt[min(ek+1,MX)];
 69         for(int i=1;i<=top;++i)
 70         {
 71             int to=stk[i];
 72             if(k>=dep[to])
 73                 ansnode[to]+=selfcnt[min(k-dep[to],max_dep[f])]-soncnt[min(k-dep[to],MX)];
 74             if(ek>=dep[to]-1)
 75                 ansedge[Dep[to]>Dep[anc[to]]?id[to]:id[anc[to]]]+=selfcnt[min(ek-dep[to]+1,max_dep[f])]-soncnt[min(ek-dep[to]+1,MX)];
 76         }
 77         for(int i=1;i<=MX;++i)soncnt[i]=0;
 78     }
 79     void solve(int u,int f)
 80     {
 81         vis[u]=1;
 82         get_self(u,f,0);
 83         for(int i=1;i<=max_dep[u];++i)selfcnt[i]+=selfcnt[i-1];
 84         ansnode[u]+=selfcnt[min(k,max_dep[u])];
 85 //        if(f!=0)ansedge[Dep[u]>Dep[f]?id[u]:id[f]]+=selfcnt[min(ek,max_dep[u]+(Dep[u]>Dep[f]?-1:0))];
 86         for(int i=head[u];i;i=edge[i].next)
 87         {
 88             int to=edge[i].to;
 89             if(vis[to])continue;
 90             workson(to,u);
 91         }
 92         for(int i=0;i<=max_dep[u];++i)selfcnt[i]=0;
 93         for(int i=head[u];i;i=edge[i].next)
 94         {
 95             int to=edge[i].to;
 96             if(vis[to])continue;
 97             respart=inf;//ans是找rt用的
 98             get_gravity(to,0,sz[to]);
 99             solve(rt,u);
100         }
101     }
102     //====================题目函数
103 }TrDiv;
104 
105 void TotInit(int n){
106     for(int i=0;i<=n;++i)ansedge[i]=ansnode[i]=max_dep[i]=0;
107     Init(n);
108     TrDiv.Init(n);
109 }
110 int ttt;
111 int el[N],er[N];
112 void Dfs(int u,int f)
113 {
114     Dep[u]=Dep[f]+1;
115     for(int i=head[u];i;i=edge[i].next)
116     {
117         int to=edge[i].to;
118         if(to==f)continue;
119         Dfs(to,u);
120         id[to]=edge[i].id;
121     }
122 }
123 void solve()
124 {
125     mp.clear();
126     ttt++;
127     int n;
128     FI(n),FI(k);
129     ek=(k-1)/2;
130     k/=2;
131     TotInit(n);
132     for(int i=1;i<n;++i)
133     {
134         int u,v;
135         FI(u),FI(v);
136     //    if(u>v)swap(u,v);
137         add(u,v,i);
138         add(v,u,i);
139     //    el[i]=u,er[i]=v;
140     //    mp[1ll*1000000*v+u]=i;
141     }
142     Dfs(1,0);
143     TrDiv.respart=inf;
144     TrDiv.get_gravity(1,0,n);
145     int rt=TrDiv.rt;
146     TrDiv.solve(rt,0);
147     int ans=0;
148     for(int i=1;i<=n;++i)ans=max(ans,ansnode[i]);
149     for(int i=1;i<n;++i)ans=max(ans,ansedge[i]);
150     FO(n-ans);
151     FO('
');
152 }