POJ 2114 Boatherds 点分治

电玩女神 2022-08-02 09:46 220阅读 0赞

问是否存在长度等于K的路径。就是将统计小于等于K的换成统计等于K的条数,只要最后统计出来的等于K的数量大于0就是存在。其他一点没变,还是那个论文题的点分治。

  1. // whn6325689
  2. // Mr.Phoebe
  3. // http://blog.csdn.net/u013007900
  4. #include <algorithm>
  5. #include <iostream>
  6. #include <iomanip>
  7. #include <cstring>
  8. #include <climits>
  9. #include <complex>
  10. #include <fstream>
  11. #include <cassert>
  12. #include <cstdio>
  13. #include <bitset>
  14. #include <vector>
  15. #include <deque>
  16. #include <queue>
  17. #include <stack>
  18. #include <ctime>
  19. #include <set>
  20. #include <map>
  21. #include <cmath>
  22. #include <functional>
  23. #include <numeric>
  24. #pragma comment(linker, "/STACK:1024000000,1024000000")
  25. using namespace std;
  26. #define eps 1e-9
  27. #define PI acos(-1.0)
  28. #define INF 0x3f3f3f3f
  29. #define LLINF 1LL<<62
  30. #define speed std::ios::sync_with_stdio(false);
  31. typedef long long ll;
  32. typedef unsigned long long ull;
  33. typedef long double ld;
  34. typedef pair<ll, ll> pll;
  35. typedef complex<ld> point;
  36. typedef pair<int, int> pii;
  37. typedef pair<pii, int> piii;
  38. typedef vector<int> vi;
  39. #define CLR(x,y) memset(x,y,sizeof(x))
  40. #define CPY(x,y) memcpy(x,y,sizeof(x))
  41. #define clr(a,x,size) memset(a,x,sizeof(a[0])*(size))
  42. #define cpy(a,x,size) memcpy(a,x,sizeof(a[0])*(size))
  43. #define mp(x,y) make_pair(x,y)
  44. #define pb(x) push_back(x)
  45. #define lowbit(x) (x&(-x))
  46. #define MID(x,y) (x+((y-x)>>1))
  47. #define ls (idx<<1)
  48. #define rs (idx<<1|1)
  49. #define lson ls,l,mid
  50. #define rson rs,mid+1,r
  51. #define root 1,1,n
  52. template<class T>
  53. inline bool read(T &n)
  54. {
  55. T x = 0, tmp = 1;
  56. char c = getchar();
  57. while((c < '0' || c > '9') && c != '-' && c != EOF) c = getchar();
  58. if(c == EOF) return false;
  59. if(c == '-') c = getchar(), tmp = -1;
  60. while(c >= '0' && c <= '9') x *= 10, x += (c - '0'),c = getchar();
  61. n = x*tmp;
  62. return true;
  63. }
  64. template <class T>
  65. inline void write(T n)
  66. {
  67. if(n < 0)
  68. {
  69. putchar('-');
  70. n = -n;
  71. }
  72. int len = 0,data[20];
  73. while(n)
  74. {
  75. data[len++] = n%10;
  76. n /= 10;
  77. }
  78. if(!len) data[len++] = 0;
  79. while(len--) putchar(data[len]+48);
  80. }
  81. //-----------------------------------
  82. const int MAXN=10010;
  83. struct Edge
  84. {
  85. int to,nex,c;
  86. }e[MAXN<<1];
  87. int head[MAXN],tot;
  88. bool vis[MAXN];
  89. int siz[MAXN],dep[MAXN],num[MAXN];
  90. int s[MAXN];
  91. int n,k,tot_size;
  92. int rot,top,ans;
  93. void init()
  94. {
  95. tot=ans=rot=0;
  96. CLR(head,-1);CLR(vis,0);
  97. num[0]=n;tot_size=n;
  98. }
  99. void addedge(int u,int v,int c)
  100. {
  101. e[tot].to=v;
  102. e[tot].nex=head[u];
  103. e[tot].c=c;
  104. head[u]=tot++;
  105. }
  106. void get_root(int u,int fa=-1)
  107. {
  108. siz[u]=1;num[u]=0;
  109. int v;
  110. for(int i=head[u];~i;i=e[i].nex)
  111. {
  112. v=e[i].to;
  113. if(!vis[v] && v!=fa)
  114. {
  115. get_root(v,u);
  116. siz[u]+=siz[v];
  117. num[u]=max(num[u],siz[v]);
  118. }
  119. }
  120. num[u]=max(num[u],tot_size-siz[u]);
  121. if(num[u]<num[rot]) rot=u;
  122. }
  123. void get_dep(int u,int fa=-1)
  124. {
  125. if(dep[u]<=k) s[top++]=dep[u];
  126. siz[u]=1;
  127. int v;
  128. for(int i=head[u];~i;i=e[i].nex)
  129. {
  130. v=e[i].to;
  131. if(!vis[v]&&v!=fa)
  132. {
  133. dep[v]=dep[u]+e[i].c;
  134. get_dep(v,u);
  135. siz[u]+=siz[v];
  136. }
  137. }
  138. }
  139. int getsum(int u,int len)
  140. {
  141. dep[u]=len;top=0;
  142. get_dep(u);
  143. sort(s,s+top);
  144. int ans=0;
  145. for(int l=0,r=top-1;l<r;l++)
  146. {
  147. while(l<r && s[l]+s[r]>k)
  148. r--;
  149. ans+=r-l;
  150. }
  151. for(int l=0,r=top-1;l<r;l++)
  152. {
  153. while(l<r && s[l]+s[r]>=k)
  154. r--;
  155. ans-=r-l;
  156. }
  157. return ans;
  158. }
  159. void dfs(int u,int fa=-1)
  160. {
  161. vis[u]=1;
  162. ans+=getsum(u,0);
  163. int v;
  164. for(int i=head[u];~i;i=e[i].nex)
  165. {
  166. v=e[i].to;
  167. if(!vis[v]&&v!=fa)
  168. {
  169. ans-=getsum(v,e[i].c);
  170. rot=0;tot_size=siz[v];
  171. get_root(v);
  172. dfs(rot);
  173. }
  174. }
  175. }
  176. int main()
  177. {
  178. while(read(n) && n)
  179. {
  180. init();
  181. for(int u=1,v,w;u<=n;u++)
  182. {
  183. while(read(v) && v)
  184. {
  185. read(w);
  186. addedge(u,v,w);
  187. addedge(v,u,w);
  188. }
  189. }
  190. while(read(k) && k)
  191. {
  192. ans=0,tot_size=n,rot=0;
  193. CLR(vis,0);
  194. get_root(1);
  195. dfs(rot);
  196. puts(ans?"AYE":"NAY");
  197. }
  198. puts(".");
  199. }
  200. return 0;
  201. }

玮神告诉我所以分治算法的精髓都在于合并的过程,树分治也是同样的。
树分治的难点在于怎么计算跨过root,在几颗子树之间的答案。其次就是如果算重的话,要将同一棵子树上面的答案消除。

发表评论

表情:
评论列表 (有 0 条评论,220人围观)

还没有评论,来说两句吧...

相关阅读

    相关 分治-模板

    可能一步步克服恐惧的过程就是成功,所以只管面对恐惧,不思考结果, 24分钟敲模板,这是点分治第一次敲的这么顺利,纪念一下。 洛谷:2634.求距离是三的倍数的点对数

    相关 POJ 2114 Boatherds 分治

    问是否存在长度等于K的路径。就是将统计小于等于K的换成统计等于K的条数,只要最后统计出来的等于K的数量大于0就是存在。其他一点没变,还是那个论文题的点分治。 // w

    相关 分治初步

      点分治是一种常用于处理树上点对关系的分治算法。   一、算法介绍   提到点分治,我们先来看一道例题:[洛谷P3806 【模板】点分治1][P3806 _1]

    相关 分治学习笔记

    哗我看了一下好像没有很详细专门讲分治的blog?那就主要先学一下点分治吧,其他的……等我记得把C++一本通带到机房来再说吧先咕着啦 > 写在前面 > > 刷题进度 > >

    相关 分治

      [传送门][Link 1](洛谷) UPDATE:关于代码中时间复杂度的更正——在代码中每一次都要通过遍历一遍询问来得到答案,所以时间复杂度是O(NMlogN), !

    相关 [笔记]分治

    基本思路:点分治,是一种针对可带权树上简单路径统计问题的算法。对于一个节点,只解决经过这棵子树的根节点的路径,对于子节点问题下推子树。 //当初的主要问题是vis[]

    相关 分治学习笔记

    点分治 关于点分治,其实思想是非常好理解的,类比在数列上或是在平面上的分治算法(如归并排序,平面最近点对等),我们可以从字面上理解该算法: > 以一个点为界限,将一棵树