3700: 发展城市
Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 18 Solved: 8
[ Submit][ Status][ Discuss]
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,速度为v
Output
对于每个T,输出一行,表示顾客的碰面次数。
Sample Input
3
1 2 1
2 3 1
3
1 3 2
3 1 1
1 2 3
1
0
Sample Output
0
HINT
【数据规模】
1<=T<=20 1<=N<=10^5 0<=M<=10^3 1<=V<=10^6 1<=Z<=10^3
Source
#include<iostream>
#include<cstdio>
#include<queue>
#include<vector>
#include<bitset>
#include<algorithm>
#include<cstring>
#include<map>
#include<stack>
#include<set>
#include<cmath>
#include<ext/pb_ds/priority_queue.hpp>
using namespace std;
const int maxn = 1E5 + 10;
typedef double DB;
typedef long long LL;
const DB eps = 1E-10;
struct E{
int to,z;
E(){}
E(int to,int z): to(to),z(z){}
};
int gcd(int x,int y) {return !y?x:gcd(y,x%y);}
struct data{
int A,B;
data(int _A = 1,int _B = 1) {
int G = gcd(_A,_B);
A = _A/G; B = _B/G;
}
bool operator <= (const data &b) const {
if (A == b.A && B == b.B) return 1;
LL A1 = 1LL*A*b.B;
LL A2 = 1LL*b.A*B;
return A1 < A2;
}
bool operator == (const data &b) const {
return A == b.A && B == b.B;
}
bool operator < (const data &b) const {
LL A1 = 1LL*A*b.B;
LL A2 = 1LL*b.A*B;
return A1 < A2;
}
}tim[2][5];
int T,n,m,dfs_clock,L[maxn],fa[maxn][20],s[1010],t[1010],DD[2][5],
Log[maxn*2],deep[maxn*2][20],pos[maxn],ans[maxn*2][20]
,pass[2][5],w[1010],now[10],Dis[maxn],bin[maxn*2];
vector <E> v[maxn];
void dfs(int x,int from)
{
pos[x] = ++dfs_clock;
ans[dfs_clock][0] = x;
deep[dfs_clock][0] = L[x];
for (int i = 0; i < v[x].size(); i++) {
int to = v[x][i].to;
if (to == from) continue;
fa[to][0] = x;
Dis[to] = Dis[x] + v[x][i].z;
L[to] = L[x] + 1;
dfs(to,x);
ans[++dfs_clock][0] = x;
deep[dfs_clock][0] = L[x];
}
}
int LCA(int p,int q)
{
int pa = pos[p],pb = pos[q];
if (pa > pb) swap(pa,pb);
int t = Log[pb - pa + 1];
if (deep[pa][t] <= deep[pb - bin[t] + 1][t])
return ans[pa][t];
else return ans[pb - bin[t] + 1][t];
}
bool Judge(int A,int B,int Lca,int k)
{
if (k == Lca) return 1;
if (L[k] <= L[Lca]) return 0;
if (k == A) return 1;
if (k == B) return 1;
if (L[k] < L[A]) {
int lca = LCA(A,k);
if (lca == k) return 1;
}
if (L[k] < L[B]) {
int lca = LCA(B,k);
if (lca == k) return 1;
}
return 0;
}
int dist(int A,int B)
{
int Lca = LCA(A,B);
return Dis[A] + Dis[B] - 2*Dis[Lca];
}
int getint()
{
char ch = getchar();
int ret = 0;
while (ch < '0' || '9' < ch) ch = getchar();
while ('0' <= ch && ch <= '9')
ret = ret*10 + ch - '0',ch = getchar();
return ret;
}
void LCApre()
{
for (int i = 1; i < 20; i++)
for (int j = 1; j <= dfs_clock; j++) {
if (j + (1<<i) - 1 > dfs_clock) continue;
if (deep[j][i-1] < deep[j+(1<<(i-1))][i-1]) {
ans[j][i] = ans[j][i-1];
deep[j][i] = deep[j][i-1];
}
else {
ans[j][i] = ans[j+(1<<(i-1))][i-1];
deep[j][i] = deep[j+(1<<(i-1))][i-1];
}
}
}
int main()
{
freopen("3700.in","r",stdin);
freopen("3700.out","w",stdout);
//freopen("hotel7.in","r",stdin);
//freopen("DMC.txt","r",stdin);
for(int i = 2; i <= 200000; i++)
Log[i] = Log[i>>1] + 1;
bin[0] = 1;
for(int i = 1; i < 20; i++)
bin[i] = bin[i-1]<<1;
T = getint();
for (int I = 1; I <= T; I++) {
int Ans = 0;
dfs_clock = 0;
n = getint();
for (int i = 1; i < n; i++) {
int x = getint(),y = getint(),z = getint();
v[x].push_back(E(y,z));
v[y].push_back(E(x,z));
}
int Root = n/2;
L[Root] = 1; Dis[Root] = 0;
dfs(Root,0);
LCApre();
m = getint();
for (int i = 1; i <= m; i++)
s[i] = getint(),t[i] = getint(),w[i] = getint();
for (int i = 1; i < m; i++)
for (int j = i + 1; j <= m; j++) {
if (s[i] == s[j]) {
++Ans;
continue;
}
int tot = 0,Lci = LCA(s[i],t[i]),Lcj = LCA(s[j],t[j]);
int Lca = LCA(s[i],s[j]);
if (Judge(s[i],t[i],Lci,Lca) && Judge(s[j],t[j],Lcj,Lca))
now[++tot] = Lca;
Lca = LCA(s[i],t[j]);
if (Judge(s[i],t[i],Lci,Lca) && Judge(s[j],t[j],Lcj,Lca))
now[++tot] = Lca;
Lca = LCA(t[i],s[j]);
if (Judge(s[i],t[i],Lci,Lca) && Judge(s[j],t[j],Lcj,Lca))
now[++tot] = Lca;
Lca = LCA(t[i],t[j]);
if (Judge(s[i],t[i],Lci,Lca) && Judge(s[j],t[j],Lcj,Lca))
now[++tot] = Lca;
if (!tot) continue;
sort(now + 1,now + tot + 1);
int cur = 1;
for (int I = 2; I <= tot; I++)
if (now[I] != now[I-1])
now[++cur] = now[I];
if (cur == 3) {
Lca = LCA(now[1],now[2]);
if (Lca == now[3]) cur = 2;
else {
Lca = LCA(now[1],now[3]);
if (Lca == now[2]) now[2] = now[3];
else now[1] = now[3];
}
cur = 2;
}
if (cur == 1) {
int disi = dist(s[i],now[1]);
int disj = dist(s[j],now[1]);
if (1LL*disi*w[j] == 1LL*disj*w[i]) ++Ans;
}
else {
int disA = dist(s[i],now[1]);
int disB = dist(s[i],now[2]);
if (disA < disB) {
pass[0][0] = now[1];
pass[0][1] = now[2];
DD[0][0] = disA;
DD[0][1] = disB;
}
else {
pass[0][0] = now[2];
pass[0][1] = now[1];
DD[0][0] = disB;
DD[0][1] = disA;
}
disA = dist(s[j],now[1]);
disB = dist(s[j],now[2]);
if (disA < disB) {
pass[1][0] = now[1];
pass[1][1] = now[2];
DD[1][0] = disA;
DD[1][1] = disB;
}
else {
pass[1][0] = now[2];
pass[1][1] = now[1];
DD[1][0] = disB;
DD[1][1] = disA;
}
if (pass[0][0] == pass[1][0]) {
if (1LL*DD[0][0]*w[j] < 1LL*DD[1][0]*w[i]) {
if (1LL*DD[1][1]*w[i] <= 1LL*DD[0][1]*w[j]) ++Ans;
}
else if(1LL*DD[1][0]*w[i] < 1LL*DD[0][0]*w[j]) {
if (1LL*DD[0][1]*w[j] <= 1LL*DD[1][1]*w[i]) ++Ans;
}
else if (1LL*DD[0][0]*w[j] == 1LL*DD[1][0]*w[i]) ++Ans;
}
else {
if (1LL*DD[1][0]*w[i] <= 1LL*DD[0][0]*w[j] && 1LL*DD[0][0]*w[j] <= 1LL*DD[1][1]*w[i]) ++Ans;
else if (1LL*DD[0][0]*w[j] <= 1LL*DD[1][0]*w[i] && 1LL*DD[1][0]*w[i] <= 1LL*DD[0][1]*w[j]) ++Ans;
}
}
}
printf("%d\n",Ans);
for (int i = 1; i <= n; i++)
v[i].clear();
}
return 0;
}