版权声明:反正也没有人会转,下一个 https://blog.csdn.net/drtlstf/article/details/85011372
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; }