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
感觉就是这题很丧心病狂吧。路径求交,还要判断是否相遇,所以就抄了一份黄学长代码QAQ
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define double long double
using namespace std;
const int MAXN = 100005;
int first[MAXN], next[MAXN << 1], go[MAXN << 1], way[MAXN << 1], t;
int pos[MAXN], top[MAXN], size[MAXN], son[MAXN], fa[MAXN], dep[MAXN], dis[MAXN], dfn[MAXN];
int n, m, i, j, k, l, x, y, z, begi[1005], end[1005], e[4], sd[1005], u, v, T;
bool vis[MAXN];
inline int get()
{
char c;
while ((c = getchar()) < 48 || c > 57);
int res = c - 48;
while ((c = getchar()) >= 48 && c <= 57)
res = res * 10 + c - 48;
return res;
}
inline void add(const int &x, const int &y, const int &z)
{
next[++t] = first[x]; first[x] = t; go[t] = y; way[t] = z;
next[++t] = first[y]; first[y] = t; go[t] = x; way[t] = z;
}
inline void dfs(int now, int fat)
{
size[now] = 1; dfn[now] = ++t;
int son1 = 0, son2 = 0;
for(int i = first[now]; i; i = next[i])
if (go[i] != fat)
{
dep[go[i]] = dep[now] + 1;
dis[go[i]] = dis[now] + way[i];
fa[go[i]] = now;
dfs(go[i], now);
if (size[go[i]] > son1) son1 = size[go[i]], son2 = go[i];
size[now] += size[go[i]];
}
son[now] = son2;
}
inline void dfs1(int now)
{
pos[now] = ++t;
if (son[now])
{
top[son[now]] = top[now];
dfs1(son[now]);
}
for(int i = first[now]; i; i = next[i])
if (!pos[go[i]])
{
top[go[i]] = go[i];
dfs1(go[i]);
}
}
inline int getlca(int x, int y)
{
while (top[x] != top[y])
{
if (dep[top[x]] < dep[top[y]]) swap(x, y);
x = fa[top[x]];
}
if (pos[x] < pos[y]) return x;
else return y;
}
inline int getdis(int x, int y)
{
return dis[x] + dis[y] - (dis[getlca(x, y)] << 1);
}
inline int getclose(int a, int b, int c)
{
int r = getlca(a, b);
if (dfn[c] < dfn[r] || dfn[c] >= dfn[r] + size[r]) return r;
int lca1 = getlca(a, c);
if (lca1 != r) return lca1;
int lca2 = getlca(b, c);
if (lca2 != r) return lca2;
return r;
}
inline void getpath(int a, int b, int c, int d, int &u, int &v)
{
e[0] = getclose(a, b, c);
e[1] = getclose(a, b, d);
e[2] = getclose(c, d, a);
if (e[2] != e[0] && e[2] != e[1]) {u = v = 0; return;}
e[3] = getclose(c, d, b);
if (e[3] != e[0] && e[3] != e[1]) {u = v = 0; return;}
u = e[0]; v = e[1];
}
inline bool check(int x, int y)
{
if (begi[x] == begi[y]) return 1;
getpath(begi[x], end[x], begi[y], end[y], u, v);
if (!u) return 0;
if (u == v) return ((double)getdis(begi[x], u) / sd[x] == (double)getdis(begi[y], u) / sd[y]);
if (getdis(u, begi[x]) > getdis(v, begi[x])) swap(u, v);
if (getclose(u, v, begi[x]) == getclose(u, v, begi[y]))
{
double tim1 = (double)getdis(begi[x], u) / sd[x], tim2 = (double)getdis(begi[y], u) / sd[y];
if (tim1 == tim2) return 1;
if (tim1 > tim2) swap(x, y);
return ((double)getdis(begi[x], v) / sd[x] >= (double)getdis(begi[y], v) / sd[y]);
}
return ((double)getdis(begi[x], u) / sd[x] <= (double)getdis(begi[y], u) / sd[y] &&
(double)getdis(begi[y], v) / sd[y] <= (double)getdis(begi[x], v) / sd[x]);
}
int main()
{
cin >> T;
while (T --)
{
memset(first, 0, sizeof(first));
memset(pos, 0, sizeof(pos));
memset(vis, 0, sizeof(vis));
dep[1] = dis[1] = t = 0;
n = get();
for(i = 1; i < n; i ++)
{
x = get(); y = get(); z = get();
add(x, y, z);
}
t = 0;
dfs(1, 0);
t = 0;
top[1] = 1;
dfs1(1);
m = get();
for(i = 1; i <= m; i ++)
begi[i] = get(), end[i] = get(), sd[i] = get();
int ans = 0;
for(i = 1; i < m; i ++)
for(j = 1 + i; j <= m; j ++)
if (check(i, j)) ans ++;
printf("%d\n", ans);
}
}