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 }
View Code

 

posted on 2013-07-22 19:45  KimKyeYu  阅读(266)  评论(0编辑  收藏  举报

导航