LCA

详细 百度百科。

例子hdu 2586

 1 #pragma comment(linker, "/STACK:16777216")
 2 #include <iostream>
 3 #include <cstdio>
 4 #include <cstring>
 5 #include <vector>
 6 
 7 using namespace std;
 8 
 9 const int N=100001;
10 typedef pair<int,int> pii;
11 vector<pii>g[N];
12 int fa[N];
13 int check[N];
14 int ancer[N];
15 int dp[N];
16 int ans[N];
17 
18 vector<pii>h[N];
19 int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}
20 
21 void lca(int u,int f){
22     int size=g[u].size();
23     int v,id;
24     for(int i=0;i<size;i++)if(g[u][i].first!=f){
25         v=g[u][i].first;
26         dp[v]=dp[u]+g[u][i].second;
27         lca(v,u);
28         fa[v]=u;
29         ancer[find(u)]=u;
30     }
31     check[u]=1;
32     size=h[u].size();
33     for(int i=0;i<size;i++){
34         v=h[u][i].first;
35         id=h[u][i].second;
36         if(check[v]){
37             ans[id]=dp[u]+dp[v]-2*dp[ancer[find(v)]];
38         }
39     }
40 }
41 void init(int n){
42     for(int i=0;i<=n;i++)fa[i]=i;
43     memset(check,0,sizeof(int)*(n+1));
44     for(int i=0;i<=n;i++){g[i].clear();h[i].clear();}
45     dp[1]=0;
46 }
47 int main()
48 {
49     int n,m;
50     int x,y,k;
51     int T;
52     cin>>T;
53     while(T--){
54         scanf("%d%d",&n,&m);
55         init(n);
56         for(int i=1;i<n;i++){
57             scanf("%d%d%d",&x,&y,&k);
58             g[x].push_back(make_pair(y,k));
59             g[y].push_back(make_pair(x,k));
60         }
61         for(int i=1;i<=m;i++){
62             scanf("%d%d",&x,&y);
63             h[x].push_back(make_pair(y,i));
64             h[y].push_back(make_pair(x,i));
65         }
66         lca(1,-1);
67         for(int i=1;i<=m;i++){
68             printf("%d\n",ans[i]);
69         }
70     }
71 
72     return 0;
73 }
Tarjan

 

#pragma comment(linker, "/STACK:16777216")
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>

using namespace std;
const int N=80000;
const int M=20;
int p[N][M];
int d[N];
int dis[N];
typedef pair<int,int> pii;
vector <pii>g[N];
void build(int u,int fa){
    p[u][0]=fa;
    d[u]=d[fa]+1;
    for(int i=1;i<M;i++){
        p[u][i]=p[p[u][i-1]][i-1];
    }
    int size=g[u].size();
    for(int i=0;i<size;i++)if(g[u][i].first!=fa){
        int v=g[u][i].first;
        dis[v]=dis[u]+g[u][i].second;
        build(v,u);
    }
}
int find(int a,int k){
    for(int i=0;k;i++,k>>=1){
        if(k&1)a=p[a][i];
    }
    return a;
}
int lca(int a,int b){
    if(d[a]>d[b])
        swap(a,b);
    b=find(b,d[b]-d[a]);
    if(a!=b){
        for(int j=M-1;j>=0;j--){
            if(p[a][j]!=p[b][j]){
                a=p[a][j],b=p[b][j];
            }
        }
        a=p[a][0],b=p[b][0];
    }
    return a;
}
void init(int n){
    for(int i=0;i<=n;i++)g[i].clear();
    memset(d,0,sizeof(d));
    memset(dis,0,sizeof(dis));
}
int main()
{
    int T;
    cin>>T;
    int n,m;
    int u,v,w;
    while(T--){
        scanf("%d%d",&n,&m);init(n);
        for(int i=1;i<n;i++){
            scanf("%d%d%d",&u,&v,&w);
            g[u].push_back(make_pair(v,w));
            g[v].push_back(make_pair(u,w));
        }

        build(1,-1);
        for(int i=1;i<=m;i++){
            scanf("%d%d",&u,&v);
            int cao=lca(u,v);
            printf("%d\n",dis[u]+dis[v]-2*dis[cao]);
        }
        //puts("");
    }
    return 0;
}

倍增法
倍增

 

posted @ 2014-09-17 19:42  Mr.Youyu  阅读(220)  评论(0)    收藏  举报