LCA离线模板(Tarjan)倍增模板 hdu2586

来源:互联网 发布:b2b源码php 编辑:程序博客网 时间:2024/05/22 10:07

How far away ?

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 17189    Accepted Submission(s): 6618


Problem Description
There are n houses in the village and some bidirectional roads connecting them. Every day peole always like to ask like this "How far is it if I want to go from house A to house B"? Usually it hard to answer. But luckily int this village the answer is always unique, since the roads are built in the way that there is a unique simple path("simple" means you can't visit a place twice) between every two houses. Yout task is to answer all these curious people.
 

Input
First line is a single integer T(T<=10), indicating the number of test cases.
  For each test case,in the first line there are two numbers n(2<=n<=40000) and m (1<=m<=200),the number of houses and the number of queries. The following n-1 lines each consisting three numbers i,j,k, separated bu a single space, meaning that there is a road connecting house i and house j,with length k(0<k<=40000).The houses are labeled from 1 to n.
  Next m lines each has distinct integers i and j, you areato answer the distance between house i and house j.
 

Output
For each test case,output m lines. Each line represents the answer of the query. Output a bland line after each test case.
 

Sample Input
23 21 2 103 1 151 22 32 21 2 1001 22 1
 

Sample Output
1025100100
Tarjan:
#include<bits/stdc++.h>using namespace std;typedef long long LL;const int N = 50005;const LL mod=1e9+7;const int inf = 0x3f3f3f3f;struct edg{    int v,w;    edg(int a,int b)    {        v=a;        w=b;    }};struct node{    int x,i;    node(int a,int b)    {        x=a;        i=b;    }} ;vector<edg>v[N];vector<node>query[N];int fa[N],dis[N],ans[N],LCA[N];bool vis[N];int n;void Init(){    for(int i=1;i<=n;i++)    {        v[i].clear();        query[i].clear();        fa[i]=i;        dis[i]=0;        LCA[i]=-1;        vis[i]=false;    }    return ;}int Find(int x){    if(fa[x]==x)        return x;    return fa[x]=Find(fa[x]);}void Union(int x,int y){    x=Find(x);    y=Find(y);    fa[y]=x;    return ;}void Tarjan(int s,int f){    dis[s]=f;    vis[s]=true;    int l=v[s].size();    for(int i=0;i<l;i++)    {        int x=v[s][i].v;        int w=v[s][i].w;        if(vis[x])continue;        Tarjan(x,f+w);        Union(s,x);    }    l=query[s].size();    for(int i=0;i<l;i++)    {        int x=query[s][i].x;        int y=query[s][i].i;        if(!vis[x])continue;        LCA[y]=Find(x);        ans[y]=dis[x]+dis[s]-2*dis[Find(x)];    }    return ;}int main(){    int t;    scanf("%d",&t);    while(t--)    {        int q,x,y,z;        scanf("%d%d",&n,&q);        Init();        for(int i=1;i<n;i++)        {            scanf("%d%d%d",&x,&y,&z);            v[x].push_back(edg(y,z));            v[y].push_back(edg(x,z));        }        for(int i=0;i<q;i++)        {            scanf("%d%d",&x,&y);            query[x].push_back(node(y,i));            query[y].push_back(node(x,i));        }        Tarjan(1,0);//最近公共祖先在LCA数组里        for(int i=0;i<q;i++)            printf("%d\n",ans[i]);    }    return 0;}
倍增:
#include<bits/stdc++.h>using namespace std;typedef long long LL;const int N = 50005;const int inf = 0x3f3f3f3f;struct edg{    int v,w,next;}E[N*2];int cnt,n;int head[N];int deep[N];int in[N];int dis[N];int fa[N][31];void add(int u,int v,int w){    E[cnt].v=v;E[cnt].w=w;E[cnt].next=head[u];head[u]=cnt++;    E[cnt].v=u;E[cnt].w=w;E[cnt].next=head[v];head[v]=cnt++;}void dfs(int u,int f,int dep,int dist){    deep[u]=dep;    dis[u]=dist;    fa[u][0]=f;    for(int i=head[u];i!=-1;i=E[i].next)    {        int v=E[i].v;        int w=E[i].w;        if(!deep[v])            dfs(v,u,dep+1,dist+w);    }    return ;}void Init(){    for(int j=1;(1<<j)<=n;j++)        for(int i=1;i<=n;i++)        fa[i][j]=fa[fa[i][j-1]][j-1];}int LCA(int u,int v){    if(deep[u]<deep[v])        u=u^v,v=u^v,u=u^v;    int d=deep[u]-deep[v];    for(int i=0;(1<<i)<=d;i++)        if((1<<i)&d)        u=fa[u][i];    if(u==v)        return u;    for(int i=20;i>=0;i--)        if(fa[u][i]!=fa[v][i])        u=fa[u][i],v=fa[v][i];    return fa[u][0];}int main(){    int t;    scanf("%d",&t);    while(t--)    {        int q,x,y,z;        scanf("%d%d",&n,&q);        cnt=0;        memset(head,-1,sizeof(head));        for(int i=1;i<n;i++)        {            scanf("%d%d%d",&x,&y,&z);            add(x,y,z);        }        memset(deep,0,sizeof(deep));        dfs(1,-1,1,0);        Init();        while(q--)        {            scanf("%d%d",&x,&y);            printf("%d\n",dis[x]+dis[y]-2*dis[LCA(x,y)]);        }    }    return 0;}



 
原创粉丝点击