发展城市
Time Limit: 20 Sec Memory Limit: 512 MB[][][]Description
众所周知,Hzwer学长是一名高富帅,他打算投入巨资发展一些小城市。
Hzwer打算在城市中开N个宾馆,由于Hzwer非常壕,所以宾馆必须建在空中,但是这样就必须建立宾馆之间的连接通道。机智的Hzwer在宾馆中修建了N-1条隧道,也就是说,宾馆和隧道形成了一个树形结构。 Hzwer有时候会花一天时间去视察某个城市,当来到一个城市之后,Hzwer会分析这些宾馆的顾客情况。对于每个顾客,Hzwer用三个数值描述他:(S, T, V)表示该顾客这天想要从宾馆S走到宾馆T,他的速度是V。 Hzwer需要做一些收集一些数据,这样他就可以规划他接下来的投资。 其中有一项数据就是收集所有顾客可能的碰面次数。 每天清晨,顾客同时从S出发以V的速度前往T(注意S可能等于T),当到达了宾馆T的时候,顾客显然要找个房间住下,那么别的顾客再经过这里就不会碰面了。特别的,两个顾客同时到达一个宾馆是可以碰面的。同样,两个顾客同时从某宾馆出发也会碰面。Input
第一行一个正整数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,速度为vOutput
对于每个T,输出一行,表示顾客的碰面次数。
Sample Input
Sample Output
HINT
1<=T<=20 1<=N<=10^5 0<=M<=10^3 1<=V<=10^6 1<=Z<=10^3
Main idea
给定若干个顾客,每个顾客会匀速从一个点走到另外一个点,问有几对人会在路上相遇。
Solution
由于人数较少,所以我们可以O(m^2)判断两人是否相交。
首先,两个人相遇只可能是在路径重叠的部分相遇,所以我们先对两人的路径求交,这里提供一种对树上路径求交的方法:
求出AB两人路径的交:
设A路径为a.u->a.v,B路径为b.u->b.v。那么我们求出 LCA(a.u,b.u),LCA(a.v,b.v),LCA(a.u,b.v),LCA(b.u,a.v),然后保留下在AB路径上的点。(判断一个点是否在路径上:若u在LCA(x,y)的子树中,且u为LCA(u,x)或者LCA(u,y),则u在路径x,y上),然后按照dfs序位置排序,去重,保留下后两个点,则后两个点即是路径的端点。但是这样求交的话需要多次查询LCA,我们用每次log的时间查询显然会超时,于是我们引进O(nlog(n))预处理,O(1)查询的LCA。
O(1)查询的LCA:
我们先求出对于这棵树的欧拉序(欧拉序:记下每个点第一次访问的位置以及回溯完的位置),然后我们用那么这时候x,y之间的LCA也就是 [pos[x],pos[y]] 区间内深度最小的点(pos[x]表示点x第一次在欧拉序中出现的位置),这个区间最小值用RMQ求即可。现在我们已经求出了路径的交集,然后我们暴力分类讨论一下。如果没有交集则必然不相交,若交于一点判断一下到达时间即可,否则:
先考虑两人运动的方向。我们记录p.u,p.v表示路径交集的两个端点。A1表示A到先进入路径的端点,A2表示A后到的端点,B1、B2类似(用距离长短判断即可),如果A1=B1则表示两人同向运动,否则表示相向运动。然后我们讨论一下:
同向运动:如果两人同向运动,那么若先进入路径的后离开路径,则两人会相遇。
相向运动:如果两人相向运动,则我们记录到端点的时间,如果两个人在路径上的时间有交集的话,则会相遇。然后这样判断一下就可以求出答案了,但是由于double定义下的除法速度很慢,会被卡常数,所以我们再用在long long定义下的交叉相乘来判断以上情况。这样我们就解决了这道题\(≧▽≦)/
Code
1 #include2 #include 3 #include 4 #include 5 #include 6 #include 7 using namespace std; 8 typedef long long s64; 9 10 const int ONE = 100005; 11 12 int T; 13 int n,m; 14 int x,y,z; 15 int next[ONE*2],first[ONE],go[ONE*2],w[ONE*2],tot; 16 int pos[ONE],dfn_cnt,Dep[ONE],size[ONE]; 17 int MinD[ONE*2][18],NumD[ONE*2][18]; 18 int Log[ONE*2],Bin[18]; 19 int Stk[5],top,fc; 20 int Ans; 21 s64 d[ONE]; 22 23 struct power 24 { 25 int u,v; 26 int val; 27 }a[1005],p; 28 29 namespace input 30 { 31 const int BufferSize = 1 << 16 | 1; 32 33 char buffer[BufferSize]; 34 char *head = buffer + BufferSize; 35 const char *tail = head; 36 37 inline char nextChar() 38 { 39 if (head == tail) 40 { 41 fread(buffer, 1, BufferSize, stdin); 42 head = buffer; 43 } 44 return *head++; 45 } 46 47 inline int get() 48 { 49 static char c; 50 while ((c = nextChar()) < '0' || c > '9'); 51 52 int res = c - '0'; 53 while ((c = nextChar()) >= '0' && c <= '9') 54 res = res * 10 + c - '0'; 55 return res; 56 } 57 } 58 using input::get; 59 60 inline void Add(int u,int v,int z) 61 { 62 next[++tot]=first[u]; first[u]=tot; go[tot]=v; w[tot]=z; 63 next[++tot]=first[v]; first[v]=tot; go[tot]=u; w[tot]=z; 64 } 65 66 namespace F 67 { 68 int Dfs(int u,int father) 69 { 70 pos[u] = ++dfn_cnt; 71 Dep[u] = Dep[father] + 1; 72 size[u] = 1; 73 MinD[dfn_cnt][0]=Dep[u]; NumD[dfn_cnt][0]=u; 74 for(int e=first[u];e;e=next[e]) 75 { 76 int v=go[e]; 77 if(v==father) continue; 78 d[v] = d[u] + w[e]; 79 Dep[v] = Dep[u] + 1; 80 Dfs(v,u); 81 size[u] += size[v]; 82 MinD[++dfn_cnt][0]=Dep[u]; NumD[dfn_cnt][0]=u; 83 } 84 } 85 86 inline void Pre_Rmq() 87 { 88 for(int j=1;j<=17;j++) 89 for(int i=1;i<=dfn_cnt;i++) 90 if(i+Bin[j]-1 <= dfn_cnt) 91 { 92 int Next = i + Bin[j-1]; 93 if(MinD[i][j-1] < MinD[Next][j-1]) 94 MinD[i][j]=MinD[i][j-1], NumD[i][j]=NumD[i][j-1]; 95 else 96 MinD[i][j]=MinD[Next][j-1], NumD[i][j]=NumD[Next][j-1]; 97 } 98 else break; 99 }100 }101 102 inline int LCA(int x,int y)103 {104 x=pos[x]; y=pos[y];105 if(x > y) swap(x,y);106 int T = Log[y - x +1];107 if(MinD[x][T] < MinD[y-Bin[T]+1][T]) return NumD[x][T];108 return NumD[y-Bin[T]+1][T];109 }110 111 inline s64 dist(int x,int y)112 {113 return d[x] + d[y] - (d[LCA(x,y)] << 1) ;114 }115 116 namespace PD117 {118 inline bool inroad(int u,power a)119 {120 int lca = LCA(a.u,a.v);121 if(LCA(u,lca) != lca) return 0;122 return (LCA(u,a.u)==u || LCA(u,a.v)==u);123 }124 }125 126 inline void Sort(int n)127 {128 for(int i=1;i<=n;i++)129 for(int j=i+1;j<=n;j++)130 if(pos[Stk[i]] > pos[Stk[j]])131 swap(Stk[i], Stk[j]);132 }133 134 inline power Get_road(power a,power b)135 {136 fc=top=0;137 Stk[++fc] = LCA(a.u,b.u); Stk[++fc] = LCA(a.v,b.v);138 Stk[++fc] = LCA(a.u,b.v); Stk[++fc] = LCA(b.u,a.v);139 for(int i=1;i<=fc;i++) 140 if(PD::inroad(Stk[i],a) && PD::inroad(Stk[i],b))141 Stk[++top] = Stk[i];142 143 Sort(top);144 top=unique(Stk+1,Stk+top+1) - Stk - 1;145 146 power p; p.val = 0;147 if(top==0) p.u = p.v = 0;148 if(top==1) p.u = p.v = Stk[1];149 if(top==2) p.u=Stk[1], p.v=Stk[2];150 if(top==3) p.u=Stk[2], p.v=Stk[3];151 return p;152 }153 154 inline bool pmin(s64 a,s64 b,s64 c)155 {156 if(a<=b && b<=c) return 1;157 return 0;158 }159 160 inline int Deal(int x,int y)161 {162 if(a[x].u == a[y].u) return 1;163 p = Get_road(a[x],a[y]);164 if(p.u==p.v)165 {166 if(!p.u) return 0;167 return (s64) dist(a[x].u,p.u) * a[y].val == (s64) dist(a[y].u,p.u) * a[x].val;168 }169 170 int A1,A2,B1,B2;171 double A1_time,A2_time,B1_time,B2_time; 172 if(dist(a[x].u,p.u) < dist(a[x].u,p.v)) A1=p.u, A2=p.v;else A1=p.v, A2=p.u;173 if(dist(a[y].u,p.u) < dist(a[y].u,p.v)) B1=p.u, B2=p.v;else B1=p.v, B2=p.u;174 175 A1_time=(s64)dist(A1,a[x].u)*a[y].val; A2_time=(s64)dist(A2,a[x].u)*a[y].val;176 B1_time=(s64)dist(B1,a[y].u)*a[x].val; B2_time=(s64)dist(B2,a[y].u)*a[x].val;177 178 if(A1==B1)//same179 {180 if(A1_time == B1_time) return 1;181 if(A1_time < B1_time) return A2_time >= B2_time;182 return A2_time <= B2_time;183 }184 else185 {186 if(pmin(A1_time,B1_time,A2_time)) return 1;187 if(pmin(A1_time,B2_time,A2_time)) return 1;188 if(pmin(B1_time,A1_time,B2_time)) return 1;189 if(pmin(B1_time,A2_time,B2_time)) return 1;190 return 0;191 }192 }193 194 inline void Solve()195 { 196 n=get();197 dfn_cnt=tot=0;198 memset(first,0,sizeof(first));199 for(int i=1;i >1] + 1;227 Bin[0]=1; for(int i=1;i<=17; i++) Bin[i] = Bin[i-1] << 1;228 229 T=get();230 231 while(T--)232 Solve();233 }