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('\n'); 152 }