#192-[LCA]距离查询

Description

FJ希望他的奶牛们多点锻炼身体(比如马拉松什么的)。但奶牛们很不开心,因为这打破了她们一贯的特色社会主义作风(自行体会)。FJ会给出一棵树,请求出两点间最短距离。

Input

第一行:n,m。n代表节点数量,m代表边的数量。

接下来m行,每行有u,v,dis和一个字符(E/S/W/N,分别为东南西北)。u代表这条边的起点,v为终点,dis则是这条边的长度。

第m+2行为一个K,代表接下来有K个查询。

接下来K行,每行一个g,h,代表FJ想知道g到h的最短长度。

Output

K行,分别对应每个查询,输出路径最短长度。

7 6
1 6 13 E
6 3 9 E
3 5 7 S
4 1 3 N
2 4 20 W
4 7 2 S
3
1 6
1 4
2 6
  • Sample Input

13
3
36
  • Sample Output

  • 仍然是这个公式:树形结构中两点之间的距离为dis[x]+dis[y]-2*dis[lca(x,y)]。

  • #include <iostream>
    #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) // 求LCA
    {
    	int i, v;
    	
    	for (i = 0; i < graph[u].size(); ++i)
    	{
    		v = graph[u][i].to;
    		if (v == pr)
    		{
    			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;
    }
    
    int main(void)
    {
    	int n, m, k, i, x, y, w, u, v;
    	char c;
    	
    	scanf("%d%d", &n, &m);
    	while (m--)
    	{
    		scanf("%d%d%d", &x, &y, &w);
    		cin >> c; // c是废的
    		graph[x].push_back({y, w});
    		graph[y].push_back({x, w});
    	}
    	scanf("%d", &k);
    	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});
    	}
    	
    	for (i = 1; i <= n; ++i)
    	{
    		pre[i] = i;
    	}
    	q.push(1);
    	visited[1] = true;
    	while (!q.empty()) // BFS求距离
    	{
    		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);
    	
    	for (i = 1; i <= k; ++i) // 对于每个LCA的结果,输出距离
    	{
    		printf("%d\n", dis[qx[i]] + dis[qy[i]] - (dis[lca[i]] << 1));
    	}
    		
    	return 0;
    }

     

相关推荐
©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页