题意:n个村庄用n-1条路连起来,询问m次,每次为两个村庄之间的最短路径,
题解:n-1条路连接n个点,可以知道连接后的形状为树形,m次询问后输出m个答案,所以可以用离线Tarjan算法。
代码
#include<cstdio>
#include<cstring>
#define Maxn 40005
#define Maxq 205
struct node
{
int to;
int next;
int weight;
}edge[Maxn * 2];
struct Query
{
int q;
int next;
int index;
}query[Maxq * 2];
int t1, t2;
int head[Maxn], h[Maxn];
bool flag[Maxn];
int f[Maxn], ancestor[Maxn], vis[Maxn], dis[Maxn];
int answer[Maxn * 2];
void init()
{
t1 = 0;
t2 = 0;
memset(head, -1, sizeof(head));
memset(h, -1, sizeof(h));
memset(f, -1, sizeof(f));
memset(flag, false, sizeof(flag));
memset(ancestor, 0, sizeof(ancestor));
memset(vis, false, sizeof(vis));
memset(dis, 0, sizeof(dis));
}
void addedge(int u, int v, int value)
{
edge[t1].to = v;
edge[t1].weight = value;
edge[t1].next = head[u];
head[u] = t1++;
}
int find(int x)
{
if(f[x] == -1)return x;
return f[x] = find(f[x]);
}
void Union(int u, int v)
{
int x = find(u);
int y = find(v);
if(x != y)
f[x] = y;
}
void addquery(int u, int v, int index)
{
query[t2].q = v;
query[t2].next = h[u];
query[t2].index = index;
h[u] = t2++;
query[t2].q = u;
query[t2].next = h[v];
query[t2].index = index;
h[v] = t2++;
}
void LCA(int u)
{
ancestor[u] = u;
vis[u] = true;
for(int i = head[u]; i != -1; i = edge[i].next)
{
int v = edge[i].to;
if(vis[v])continue;
dis[v] = dis[u] + edge[i].weight;
LCA(v);
Union(u, v);
ancestor[find(u)] = u;
}
for(int i = h[u]; i != -1; i = query[i].next)
{
int v = query[i].q;
if(vis[v])
{
answer[query[i].index] = ancestor[find(v)];
}
}
}
int main()
{
int T;
scanf("%d", &T);
for(int t = 1; t <= T; t++)
{
int n, m;
scanf("%d %d", &n, &m);
init();
for(int i = 1; i < n; i++)
{
int x, y, z;
scanf("%d %d %d", &x, &y, &z);
flag[y] = true;
addedge(x, y, z);
addedge(y, x, z);
}
for(int i = 0; i < m; i++)
{
int x, y;
scanf("%d %d", &x, &y);
addquery(x, y, i);
//addquery(y, x, i);
}
int root;
for(int i = 1; i <= n; i++)
{
if(!flag[i])
{
root = i;
break;
}
}
LCA(root);
for(int i = 0; i < m; i++)
{
int len = dis[query[i << 1].q] + dis[query[i << 1 | 1].q] - dis[answer[i]] * 2;
printf("%d\n", len);
}
}
return 0;
}