HDU 2586 How far away? (Offline Tarjan for LCA

                                   How far away ?、

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.
InputFirst 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.OutputFor each test case,output m lines. Each line represents the answer of the query. Output a bland line after each test case.Sample Input
2
3 2
1 2 10
3 1 15
1 2
2 3

2 2
1 2 100
1 2
2 1
Sample Output
10
25
100
100

The approximate meaning of the title: ask m times under the undirected graph to ask for their nearest common ancestor

LCA template questions, carefully figured out a number of blogs, and carefully analyzed a wave. I also understood a general idea, so I knocked it out myself. It involves the idea of ​​union search and DFS.

Use dfs to find each node, and then color each point. The function of union search here is to point the same subtree to the root node of the subtree.

See this blog for details: http://blog.csdn.net/csyzcyj/article/details/10051173Click to open the link

The time complexity is O(n)+O(Q). Q is the number of visits. Of course, brute force enumeration can also achieve such operations. But the time complexity.....

code show as below:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<ctime>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<string>
#include<queue>
#include<vector>
#include<stack>
#include<list>
using namespace std;
const int maxn=40000+5;
struct node
{
    int x,y;
} p[maxn];
int cnt,ct;
int Next[maxn*200],To[maxn*200],len[maxn*200],Lext[maxn];
int head[maxn],NextQ[maxn*200],ToQ[maxn*200];
int LCA[maxn],pre[maxn],vis[maxn],dis[maxn],ask[maxn];
void add(int u,int v,int w)//存图
{
    Next[++cnt]=Lext[u];
    Lext[u]=cnt;
    To[cnt]=v;
    len[cnt]=w;
}
void addque(int u,int v,int id)//存询问
{
    NextQ[++ct]=head[u];
    head[u]=ct;
    ToQ[ct]=v;
    ask[ct]=id;
}
void init()
{
    cnt=ct=0;
    memset(LCA,0,sizeof(LCA));
    memset(Lext,-1,sizeof(Lext));
    memset(head,-1,sizeof(head));
    memset(vis,0,sizeof(vis));
    memset(pre,0,sizeof(pre));
    memset(dis,0,sizeof(dis));
    memset(p,0,sizeof(p));
}
int Find(int x)//并查集 找祖先
{
    return x==pre[x]?x:pre[x]=Find(pre[x]);
}
void tarjan(int u)//离线Tarjan求LCA 详细见推荐博客
{
    vis[u]=1;
    pre[u]=u;
    for(int i=head[u]; i!=-1; i=NextQ[i])
    {
        int v=ToQ[i];
        int id=ask[i];
        if(vis[v])
            LCA[id]=Find(v);
    }
    for(int i=Lext[u]; i!=-1; i=Next[i])
    {
        int v=To[i];
        int w=len[i];
        if(!vis[v])
        {
            dis[v]=dis[u]+w;
            tarjan(v);
            pre[v]=u;
        }
    }
}
int main()
{
    int t,n,m,u,v,w;
    scanf("%d",&t);
    while(t--)
    {
        init();
        scanf("%d %d",&n,&m);
        for(int i=1; i<=n; i++)
            pre[i]=i;//初始每个点祖先是自己
        for(int i=1; i<=n-1; i++)
        {
            scanf("%d %d %d",&u,&v,&w);//无向图 存图
            add(u,v,w);
            add(v,u,w);
        }
        for(int i=1; i<=m; i++)
        {
            scanf("%d %d",&u,&v);
            p[i].x=u;
            p[i].y=v;
            addque(u,v,i);//i为第几次询问 
            addque(v,u,i);
        }
        tarjan(1);
        for(int i=1; i<=m; i++)
            printf("%d\n",dis[p[i].x]+dis[p[i].y]-dis[LCA[i]]*2);
    }
}

Keep diving. Learn basic graph theory knowledge.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326319090&siteId=291194637