HDU 2874 Connections between cities (LCA)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2874

题意是给你n个点,m条边(无向),q个询问。接下来m行,每行两个点一个边权,而且这个图不能有环路。然后接下来q行,每行给你两个点,问你这两个点的最短距离是多少,要是不相连,则输出一串英文。

首先想到的是用(二分)倍增LCA,但是这题的坑点是两个点可能不在同一个图中,所以我dfs的时候用block[i]标记这个点属于哪一个图中,要是这个点在同一个图中,答案就是cost[u] + cost[v] - 2*cost[lca(u , v)]。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <vector>
 5 using namespace std;
 6 const int MAXN = 10005;
 7 struct data {
 8     int next , to , w;
 9 }edge[MAXN * 4];
10 int head[MAXN] , par[MAXN * 3][15] , dep[MAXN] , cont , cost[MAXN] , block[MAXN];
11 
12 void init() {
13     cont = 0;
14     //memset(par , -1 , sizeof(par));
15     memset(head , -1 , sizeof(head));
16     memset(block , 0 , sizeof(block));
17 }
18 
19 inline void add(int u , int v , int w) {
20     edge[cont].next = head[u];
21     edge[cont].to = v;
22     edge[cont].w = w;
23     head[u] = cont++;
24 }
25 
26 void dfs(int u , int p , int d , int node , int w) {
27     dep[u] = d;
28     par[u][0] = p;
29     block[u] = node;
30     cost[u] = w;
31     int v;
32     for(int i = head[u] ; ~i ; i = edge[i].next) {
33         v = edge[i].to;
34         if(v == p)
35             continue;
36         dfs(v , u , d + 1 , node , w + edge[i].w);
37     }
38 }
39 
40 int lca(int u , int v) {
41     if(dep[u] < dep[v])
42         swap(u , v);
43     for(int k = 0 ; k < 15 ; k++) {
44         if((dep[u] - dep[v]) >> k & 1) {
45             u = par[u][k];
46         }
47     }
48     if(u == v)
49         return v;
50     for(int k = 14 ; k >= 0 ; k--) {
51         if(par[u][k] != par[v][k]) {
52             u = par[u][k];
53             v = par[v][k];
54         }
55     }
56     return par[u][0];
57 }
58 
59 int main()
60 {
61     int n , m , q , u , v , w;
62     while(~scanf("%d %d %d" , &n , &m , &q)) {
63         init();
64         for(int i = 0 ; i < m ; i++) {
65             scanf("%d %d %d" , &u , &v , &w);
66             add(u , v , w);
67             add(v , u , w);
68         }
69         int f = 0;
70         for(int i = 1 ; i <= n ; i++) {
71             if(!block[i]) {
72                 dfs(i , -1 , 0 , ++f , 0);
73             }
74         }
75         for(int k = 0 ; k < 14 ; k++) {
76             for(int i = 1 ; i <= n ; i++) {
77                 if(par[i][k] <= 0)
78                     par[i][k + 1] = par[i][k];
79                 else
80                     par[i][k + 1] = par[par[i][k]][k];
81             }
82         }
83         while(q--) {
84             scanf("%d %d" , &u , &v);
85             if(block[u] != block[v]) {
86                 printf("Not connected
");
87             }
88             else {
89                 printf("%d
" , cost[u] + cost[v] - 2 * cost[lca(u , v)]);
90             }
91         }
92     }
93 }
原文地址:https://www.cnblogs.com/Recoder/p/5268707.html