1. 程式人生 > 實用技巧 >HDU多校2020 第十場 1005/6881-Tree Cutting(點分治

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 }