#189-[LCA]How far away

版权声明:反正也没有人会转,下一个 https://blog.csdn.net/drtlstf/article/details/85011357

Description

Description 

村庄里有N个机房和连接它们的一些双向道路。机房从1标记到N。f*x每天都会从某一个机房去另一个机房切水题。所以他每天都要问:“如果我想从A机房去B机房有多远”?一般情况下,这些问题很难回答。但幸运的是,在这个村庄,答案总是独一无二的,因为这些道路都是建立在每两个机房之间的的简单道路(“简单”意味着你不能访问一个地方两次)。你的任务是回答f*x的问题。 

Input 

第一行是单个整数T(T <= 10),表示测试用例的个数。对于每个测试用例,在第一行中有两个数字n(2 <= n <= 40000)和m(1 <= m <= 200),表示机房数量和查询数量。以下n-1行各包含三个数字i,j,k,分开一个空格,意味着有一条连接机房i和机房j的道路,长度为k(0 <k <= 40000)。接下来的m行有两个整数i和j,请你回答机房i和房子j之间的距离。 

Output 

对于每个测试用例,输出m行。每一行代表f*x查询的答案。 

Input


 

2
3 2
1 2 10
3 1 15
1 2
2 3
2 2
1 2 100
1 2
2 1
  • Sample Input

10
25
100
100
  • Sample Output

  • LCA,树形结构中两点之间的距离为dis[x]+dis[y]-2*dis[lca(x,y)]。

  • #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <queue>
    
    #define SIZE 40010
    
    using namespace std;
    
    struct edge // 一条边的结构
    {
    	int to, dis;
    };
    
    struct qedge // 一个问题的结构
    {
    	int to, id;
    };
    
    queue<int> q;
    vector<edge> graph[SIZE]; // 存图
    vector<qedge> qgraph[SIZE]; // 存询问
    int pre[SIZE], lca[SIZE], dis[SIZE], qx[SIZE], qy[SIZE];
    bool visited[SIZE];
    
    int find(int x) // 找祖先
    {
    	return (pre[x] != x) ? pre[x] = find(pre[x]) : x;
    }
    
    void tarjan(int u, int pr) // 离线算法
    {
    	int i, v;
    	
    	for (i = 0; i < graph[u].size(); ++i) // 美剧儿子
    	{
    		v = graph[u][i].to;
    		if (v == pr) // 保证v是儿子,不是前驱
    		{
    			continue;
    		}
    		tarjan(v, u); // 递归
    		pre[v] = u;
    	}
    	visited[u] = true; // 标记
    	for (i = 0; i < qgraph[u].size(); ++i) // 寻找询问
    	{
    		v = qgraph[u][i].to;
    		if (visited[v]) // 两个点都找到了?
    		{
    			lca[qgraph[u][i].id] = find(v); // 存储结果
    		}
    	}
    	
    	return;
    }
    
    void doit(void)
    {
    	int n, m, k, i, x, y, w, u, v; 
    	
    	scanf("%d%d", &n, &k);
    	for (i = 1; i <= n; ++i) // 初始化
    	{
    		graph[i].clear();
    		qgraph[i].clear();
    		pre[i] = i;
    	}
    	memset(visited, false, sizeof (visited));
    	for (i = 1; i < n; ++i) // 建图
    	{
    		scanf("%d%d%d", &x, &y, &w);
    		graph[x].push_back({y, w});
    		graph[y].push_back({x, w});
    	}
    	for (i = 1; i <= k; ++i) // 询问图
    	{
    		scanf("%d%d", &qx[i], &qy[i]);
    		qgraph[qx[i]].push_back({qy[i], i});
    		qgraph[qy[i]].push_back({qx[i], i});
    	}
    	
    	q.push(1);
    	visited[1] = true;
    	while (!q.empty()) // BFS求距离(不要SPFA)
    	{
    		u = q.front();
    		q.pop();
    		for (i = 0; i < graph[u].size(); ++i)
    		{
    			v = graph[u][i].to;
    			if (!visited[v])
    			{
    				visited[v] = true;
    				q.push(v);
    				dis[v] = dis[u] + graph[u][i].dis;
    			}
    		}
    	}
    	memset(visited, false, sizeof (visited));
    	tarjan(1, -1); // 找LCA
    	
    	for (i = 1; i <= k; ++i)
    	{
    		printf("%d\n", dis[qx[i]] + dis[qy[i]] - (dis[lca[i]] << 1)); // 计算距离
    	}
    		
    	return;
    }
    
    int main(void)
    {
    	int t;
    	
    	scanf("%d", &t); // 多组数据
    	while (t--)
    	{
    		doit();
    	}
    	
    	return 0;
    }

猜你喜欢

转载自blog.csdn.net/drtlstf/article/details/85011357