LCA 离线算法 Tarjan
转载一篇博客:http://www.cnblogs.com/ylfdrib/archive/2010/11/03/1867901.html
Tarjan实现: dfs + 并查集;
通过这道题体会一下把:(思路详见上面的博客)
hdu 2586 http://acm.hdu.edu.cn/showproblem.php?pid=2586
1 #include<map> 2 #include<set> 3 #include<list> 4 #include<cmath> 5 #include<ctime> 6 #include<queue> 7 #include<stack> 8 #include<cctype> 9 #include<cstdio> 10 #include<string> 11 #include<vector> 12 #include<cstdlib> 13 #include<cstring> 14 #include<iostream> 15 #include<algorithm> 16 #define MAXN 40005 17 using namespace std; 18 19 struct P 20 { 21 int v, w; 22 }; 23 struct Q 24 { 25 int v, id; 26 }; 27 vector <P> g[MAXN]; //存树 28 vector <Q> q[MAXN]; //存询问点对(u, v) 29 30 int dist[MAXN]; //dist[i]:根到i的距离 31 int vis[MAXN]; 32 int f[MAXN]; //并查集 33 int query[MAXN][3]; //存询问结果[u, v, lca(u,v)] 34 35 int find(int x){ 36 if(x != f[x]) 37 f[x] = find(f[x]); 38 return f[x]; 39 } 40 41 void add_g(int u, int v, int w){ 42 P t; 43 t.v=v, t.w=w; 44 g[u].push_back(t); 45 } 46 47 void add_q(int u, int v, int id){ 48 Q t; 49 t.v=v, t.id=id; 50 q[u].push_back(t); 51 } 52 53 void getDist(int u){ 54 vis[u] = 1; 55 for(int i=0; i<g[u].size(); i++){ 56 int v = g[u][i].v, w= g[u][i].w; 57 if(!vis[v]){ 58 dist[v] = dist[u] + w; 59 getDist(v); 60 } 61 } 62 } 63 64 void Tarjan(int u){ 65 vis[u] = 1; 66 f[u] = u; //!! 67 for(int i=0; i<q[u].size(); i++){ 68 int v = q[u][i].v, id = q[u][i].id; 69 if(vis[v]) 70 query[id][2] = find(v); 71 } 72 for(int i=0; i<g[u].size(); i++){ 73 int v = g[u][i].v, w= g[u][i].w; 74 if(!vis[v]){ 75 Tarjan(v); 76 f[v] = u; 77 } 78 } 79 } 80 81 int main() 82 { 83 //hdu 2586 84 int t; 85 cin >> t; 86 while(t--){ 87 int n, m; 88 cin >> n >> m; 89 for(int i=1; i<=n-1; i++){ 90 int u, v, w; 91 scanf("%d%d%d", &u, &v, &w); 92 add_g(u, v, w); 93 add_g(v, u, w); 94 } 95 for(int i=1; i<=m; i++){ 96 int u, v; 97 scanf("%d%d", &u, &v); 98 query[i][0] = u; 99 query[i][1] = v; 100 add_q(u, v, i); 101 add_q(v, u, i); 102 } 103 memset(vis, 0, sizeof(vis)); 104 dist[1] = 0; 105 getDist(1); //取1为根 106 memset(vis, 0, sizeof(vis)); 107 Tarjan(1); 108 for(int i=1; i<=m; i++){ 109 int u = query[i][0], v = query[i][1], 110 lca = query[i][2]; 111 printf("%d\n", dist[u]+dist[v]-2*dist[lca]); 112 } 113 for(int i=1; i<=n; i++){ 114 g[i].clear(); 115 q[i].clear(); 116 } 117 } 118 return 0; 119 }