题目描述

众所周知,Hzwer学长是一名高富帅,他打算投入巨资发展一些小城市。
 Hzwer打算在城市中开N个宾馆,由于Hzwer非常壕,所以宾馆必须建在空中,但是这样就必须建立宾馆之间的连接通道。机智的Hzwer在宾馆中修建了N-1条隧道,也就是说,宾馆和隧道形成了一个树形结构。
 Hzwer有时候会花一天时间去视察某个城市,当来到一个城市之后,Hzwer会分析这些宾馆的顾客情况。对于每个顾客,Hzwer用三个数值描述他:(S, T, V)表示该顾客这天想要从宾馆S走到宾馆T,他的速度是V。
 Hzwer需要做一些收集一些数据,这样他就可以规划他接下来的投资。
 其中有一项数据就是收集所有顾客可能的碰面次数。
 每天清晨,顾客同时从S出发以V的速度前往T(注意S可能等于T),当到达了宾馆T的时候,顾客显然要找个房间住下,那么别的顾客再经过这里就不会碰面了。特别的,两个顾客同时到达一个宾馆是可以碰面的。同样,两个顾客同时从某宾馆出发也会碰面。

输入

第一行一个正整数T(1<=T<=20),表示Hzwer发展了T个城市,并且在这T个城市分别视察一次。
 对于每个T,第一行有一个正整数N(1<=N<=10^5)表示Hzwer在这个城市开了N个宾馆。
 接下来N-1行,每行三个整数X,Y,Z表示宾馆X和宾馆Y之间有一条长度为Z的隧道
 再接下来一行M表示这天顾客的数量。
 紧跟着M行每行三个整数(S, T, V)表示该顾客会从宾馆S走到宾馆T,速度为v

输出

对于每个T,输出一行,表示顾客的碰面次数。

样例输入

1
3
1 2 1
2 3 1
3
1 3 2
3 1 1
1 2 3

样例输出

2
0

提示

【数据规模】

1<=T<=20   1<=N<=10^5   0<=M<=10^3   1<=V<=10^6   1<=Z<=10^3

这题细节好多啊,蒟蒻的我调了一下午。

考虑到m的范围比较小,因此可以两两枚举判断是否相遇。

对于两个路径,如果能够相遇,相遇点一定在两个路径的交路径上。

如何求树上路径交?

对于两个路径A(a.u,a.v)与B(b.u,b.v)求出lca(a.u,b.u),lca(a.v,b.v),lca(a.v,b.u),lca(a.u,b.v)

去掉这四个点中不在A或B路径上的点,再去重后按dfs序排序,取后两个(如果只有一个说明路径只交于一点)就是交路径的两个端点

判断出两个路径起点先到达的交路径的端点是否是同一个,如果是就说明两个顾客是同向运动,反之则是相向运动。

如果两顾客是同向运动:只要先进入交路径的顾客后走出交路径就一定相遇。

如果两顾客是相向运动:分别求出两顾客进入和走出交路径的时间,判断只要两时间段有交集就能相遇,因为除法较慢,所以转成交叉相乘判断。

在判断和求路径过程中多次求lca,用O(logn)的方法求显然会TLE,在这里采用RMQ求lca:

在dfs时求出欧拉遍历序(就是遍历到一个点存一次)及每个点第一次被遍历的位置

对于x,y两点的lca就是欧拉序上两点第一次被遍历位置之间深度最小的点,用ST表即可O(1)查询

这道题有点卡常,注意涉及到乘速度时可能会爆longlong。

  1. #include<cmath>
  2. #include<cstdio>
  3. #include<cstring>
  4. #include<iostream>
  5. #include<algorithm>
  6. #define ll long long
  7. using namespace std;
  8. inline char _read()
  9. {
  10. static char buf[100000],*p1=buf,*p2=buf;
  11. return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
  12. }
  13. inline int read()
  14. {
  15. int x=0,f=1;char ch=_read();
  16. while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=_read();}
  17. while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=_read();}
  18. return x*f;
  19. }
  20. int T,n,m;
  21. int head[100010];
  22. int s[100010];
  23. int to[200010];
  24. int next[200010];
  25. int val[200010];
  26. int d[100010];
  27. int dep[100010];
  28. int f[200010][18];
  29. int g[200010][18];
  30. int tot;
  31. int num;
  32. int x,y,z;
  33. int ans;
  34. int p[5];
  35. int cnt;
  36. int b[200010];
  37. struct miku
  38. {
  39. int u,v,w;
  40. }a[1010];
  41. inline void add(int x,int y,int z)
  42. {
  43. tot++;
  44. next[tot]=head[x];
  45. head[x]=tot;
  46. to[tot]=y;
  47. val[tot]=z;
  48. }
  49. inline void dfs(int x,int fa)
  50. {
  51. d[x]=d[fa]+1;
  52. s[x]=++num;
  53. f[num][0]=d[x];
  54. g[num][0]=x;
  55. for(int i=head[x];i;i=next[i])
  56. {
  57. if(to[i]!=fa)
  58. {
  59. dep[to[i]]=dep[x]+val[i];
  60. dfs(to[i],x);
  61. f[++num][0]=d[x];
  62. g[num][0]=x;
  63. }
  64. }
  65. }
  66. inline void ST()
  67. {
  68. for(int j=1;j<=17;j++)
  69. {
  70. for(int i=1;i<=num;i++)
  71. {
  72. if(i+(1<<j)-1>num)
  73. {
  74. break;
  75. }
  76. if(f[i][j-1]<f[i+(1<<(j-1))][j-1])
  77. {
  78. f[i][j]=f[i][j-1];
  79. g[i][j]=g[i][j-1];
  80. }
  81. else
  82. {
  83. f[i][j]=f[i+(1<<(j-1))][j-1];
  84. g[i][j]=g[i+(1<<(j-1))][j-1];
  85. }
  86. }
  87. }
  88. }
  89. inline int lca(int x,int y)
  90. {
  91. x=s[x];
  92. y=s[y];
  93. if(x>y)
  94. {
  95. swap(x,y);
  96. }
  97. int len=b[y-x+1];
  98. if(f[x][len]<f[y-(1<<len)+1][len])
  99. {
  100. return g[x][len];
  101. }
  102. else
  103. {
  104. return g[y-(1<<len)+1][len];
  105. }
  106. }
  107. inline bool find(int anc,int x,int y)
  108. {
  109. int fx=lca(a[x].u,a[x].v);
  110. int fy=lca(a[y].u,a[y].v);
  111. if(lca(fx,anc)!=fx||lca(fy,anc)!=fy)
  112. {
  113. return false;
  114. }
  115. if(fx!=lca(fx,a[x].u)&&fx!=lca(fx,a[x].v))
  116. {
  117. return false;
  118. }
  119. if(fy!=lca(fy,a[y].u)&&fy!=lca(fy,a[y].v))
  120. {
  121. return false;
  122. }
  123. return true;
  124. }
  125. inline int dis(int x,int y)
  126. {
  127. int anc=lca(x,y);
  128. return dep[x]+dep[y]-2*dep[anc];
  129. }
  130. inline bool cmp(int x,int y)
  131. {
  132. return s[x]<s[y];
  133. }
  134. inline bool cpr(ll a,ll b,ll c)
  135. {
  136. if(a<=b&&b<=c)
  137. {
  138. return 1;
  139. }
  140. else
  141. {
  142. return 0;
  143. }
  144. }
  145. inline int check(int x,int y)
  146. {
  147. if(a[x].u==a[y].u)
  148. {
  149. return 1;
  150. }
  151. int res;
  152. cnt=0;
  153. res=lca(a[x].u,a[y].u);
  154. if(find(res,x,y)){p[++cnt]=res;}
  155. res=lca(a[x].v,a[y].v);
  156. if(find(res,x,y)){p[++cnt]=res;}
  157. res=lca(a[x].u,a[y].v);
  158. if(find(res,x,y)){p[++cnt]=res;}
  159. res=lca(a[y].u,a[x].v);
  160. if(find(res,x,y)){p[++cnt]=res;}
  161. if(cnt==0)
  162. {
  163. return 0;
  164. }
  165. sort(p+1,p+1+cnt,cmp);
  166. cnt=unique(p+1,p+1+cnt)-p-1;
  167. if(cnt==1)
  168. {
  169. if(1ll*dis(a[x].u,p[1])*a[y].w==1ll*dis(a[y].u,p[1])*a[x].w)
  170. {
  171. return 1;
  172. }
  173. else
  174. {
  175. return false;
  176. }
  177. }
  178. int st=p[cnt];
  179. int ed=p[cnt-1];
  180. int A1,A2,B1,B2;
  181. ll a1,a2,b1,b2;
  182. if(dis(a[x].u,st)<dis(a[x].u,ed))
  183. {
  184. A1=st;
  185. A2=ed;
  186. }
  187. else
  188. {
  189. A1=ed;
  190. A2=st;
  191. }
  192. if(dis(a[y].u,st)<dis(a[y].u,ed))
  193. {
  194. B1=st;
  195. B2=ed;
  196. }
  197. else
  198. {
  199. B1=ed;
  200. B2=st;
  201. }
  202. a1=1ll*dis(a[x].u,A1)*a[y].w;
  203. a2=1ll*dis(a[x].u,A2)*a[y].w;
  204. b1=1ll*dis(a[y].u,B1)*a[x].w;
  205. b2=1ll*dis(a[y].u,B2)*a[x].w;
  206. if(A1==B1)
  207. {
  208. if(a1==b1)
  209. {
  210. return 1;
  211. }
  212. if(a1<b1)
  213. {
  214. return b2<=a2;
  215. }
  216. else
  217. {
  218. return a2<=b2;
  219. }
  220. }
  221. else
  222. {
  223. if(cpr(a1,b1,a2))return 1;
  224. if(cpr(a1,b2,a2))return 1;
  225. if(cpr(b1,a1,b2))return 1;
  226. if(cpr(b1,a2,b2))return 1;
  227. return 0;
  228. }
  229. }
  230. int main()
  231. {
  232. T=read();
  233. b[0]=-1;
  234. for(int i=1;i<=200010;i++)
  235. {
  236. b[i]=b[i>>1]+1;
  237. }
  238. while(T--)
  239. {
  240. memset(head,0,sizeof(head));
  241. num=0;
  242. tot=0;
  243. ans=0;
  244. n=read();
  245. for(int i=1;i<n;i++)
  246. {
  247. x=read();
  248. y=read();
  249. z=read();
  250. add(x,y,z);
  251. add(y,x,z);
  252. }
  253. dfs(1,0);
  254. ST();
  255. m=read();
  256. for(int i=1;i<=m;i++)
  257. {
  258. a[i].u=read();
  259. a[i].v=read();
  260. a[i].w=read();
  261. }
  262. for(int i=1;i<=m;i++)
  263. {
  264. for(int j=i+1;j<=m;j++)
  265. {
  266. ans+=check(i,j);
  267. }
  268. }
  269. printf("%d\n",ans);
  270. }
  271. }

BZOJ1906树上的蚂蚁&BZOJ3700发展城市——RMQ求LCA+树链的交的更多相关文章

  1. BZOJ3700: 发展城市

    BZOJ3700: 发展城市 https://lydsy.com/JudgeOnline/problem.php?id=3700 分析: 枚举两个人,先求链交,求到两个端点的时间. 链交求法:求两两\ ...

  2. 【RMQ】洛谷P3379 RMQ求LCA

    题目描述 如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先. 输入输出格式 输入格式: 第一行包含三个正整数N.M.S,分别表示树的结点个数.询问的个数和树根结点的序号. 接下来N-1行每 ...

  3. RMQ求LCA

    题目链接 rmq求LCA,interesting. 一直没有学这玩意儿是因为CTSC的Day1T2,当时我打的树剖LCA 65分,gxb打的rmq LCA 45分... 不过rmq理论复杂度还是小一点 ...

  4. dfs序+RMQ求LCA详解

    首先安利自己倍增求LCA的博客,前置(算不上)知识在此. LCA有3种求法:倍增求lca(上面qwq),树链剖分求lca(什么时候会了树链剖分再说.),还有,标题. 是的你也来和我一起学习这个了qwq ...

  5. hdu 2586 欧拉序+rmq 求lca

    题意:求树上任意两点的距离 先说下欧拉序 对这颗树来说 欧拉序为 ABDBEGBACFHFCA 那欧拉序有啥用 这里先说第一个作用 求lca 对于一个欧拉序列,我们要求的两个点在欧拉序中的第一个位置之 ...

  6. LOJ#137. 最小瓶颈路 加强版(Kruskal重构树 rmq求LCA)

    题意 三倍经验哇咔咔 #137. 最小瓶颈路 加强版 #6021. 「from CommonAnts」寻找 LCR #136. 最小瓶颈路 Sol 首先可以证明,两点之间边权最大值最小的路径一定是在最 ...

  7. Codeforces 609E (Kruskal求最小生成树+树上倍增求LCA)

    题面 传送门 题目大意: 给定一个无向连通带权图G,对于每条边(u,v,w)" role="presentation" style="position: rel ...

  8. cogs 2450. 距离 树链剖分求LCA最近公共祖先 快速求树上两点距离 详细讲解 带注释!

    2450. 距离 ★★   输入文件:distance.in   输出文件:distance.out   简单对比时间限制:1 s   内存限制:256 MB [题目描述] 在一个村子里有N个房子,一 ...

  9. 【BZOJ3700】发展城市 [LCA][RMQ]

    发展城市 Time Limit: 20 Sec  Memory Limit: 512 MB[Submit][Status][Discuss] Description 众所周知,Hzwer学长是一名高富 ...

随机推荐

  1. xrange 和range的区别

    >>> xrange(5)xrange(5)>>> list(xrange(5))[0, 1, 2, 3, 4]>>> xrange(1,5)xr ...

  2. mysql 修改字段

    alter table dev_instant_video modify column content varchar(2500)alter table dev_instant_video_info  ...

  3. Java多线程编程模式实战指南一:Active Object模式(上)

    Active Object模式简介 Active Object模式是一种异步编程模式.它通过对方法的调用与方法的执行进行解耦来提高并发性.若以任务的概念来说,Active Object模式的核心则是它 ...

  4. Kubernetes-v1.12.0基于kubeadm部署

    1.主机规划 #master节点(etcd/apiserver/scheduler/controller manager)master.example.cometh0: 192.168.0.135et ...

  5. LOJ550 Matching 构造

    传送门 题意:$T$组询问,每组询问给出一个$N \times M$的网格和一个$K$,每一次你可以消除网格中的两个块,如果两个块的曼哈顿距离小于$K$,则不会得到分数,否则得到等同于它们曼哈顿距离的 ...

  6. CF [2016-2017 ACM-ICPC CHINA-Final][GYM 101194 H] Great Cells

    很久以前做的一道思博题了,今天来补一补. 大致题意:在一个\(n*m\)的矩阵内填整数,数字在\([1,k]\)范围内.矩阵中某格的数为great number当且仅当与它同行同列的数字都严格比它小. ...

  7. [JDBC]ORA-01000: 超出打开游标的最大数(ORA-01000: maximum open cursors exceeded)

    问题产生的原因: Java代码在执行conn.createStatement()和conn.prepareStatement()的时候,相当于在数据库中打开了一个cursor.由于oracle对打开的 ...

  8. 生成线上用https证书,支持通配符和多域名,初学Let’s Encrypt用于IIS,纯本地手动

    自简书发布的上篇<生成本地测试用https证书,支持通配符和多域名,初学OpenSSL>以来,本地测试用https用的妥妥的. 线上一直用的腾讯云的免费证书(每个域名都要一个证书(滑稽), ...

  9. SpringBoot日记——Spring的安全配置-登录认证与授权

    安全是每个项目开发中都需要考虑的,比如权限控制,安全认证,防止漏洞攻击等. 比较常见的安全框架有:Apache的shiro.Spring Security等等,相信用shiro的用户群体更多,而sec ...

  10. Linux下selinux简单梳理

    在linux环境下执行某些程序时,偶尔会遇到来一个关于selinux的强制模式不可执行的情况,这种情况下需要关闭selinux或者将enforcing改为permissive模式后才能进行执行.sel ...