hdu 5286 How far away ? tarjan/lca

How far away ?

Time Limit: 20 Sec

Memory Limit: 256 MB

题目连接

http://acm.hdu.edu.cn/showproblem.php?pid=2586

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

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

HINT

 

题意

 

题解:

tarjan离线算法

代码:

 

# include<stdio.h>
# include<string.h>
# define N 40005
# define M 205
struct node{
    int from,to,next,val;
}edge[2*N];
struct node1{
    int from,to,next,num;
}edge1[2*M];
int tol,head[N],head1[N],tol1,father[N],dis[N],LCA[M],n,m;
bool visit[N];
void add(int a,int b,int c)
{
    edge[tol].from=a;edge[tol].to=b;edge[tol].next=head[a];edge[tol].val=c;head[a]=tol++;
}
void add1(int a,int b,int c)
{
    edge1[tol1].from=a;edge1[tol1].to=b;edge1[tol1].next=head1[a];edge1[tol1].num=c;head1[a]=tol1++;
}
int find(int x)
{
    if(x!=father[x])
        father[x]=find(father[x]);
    return father[x];
}
void tarjan(int u)
{
    int j,v;
    visit[u]=1;
    father[u]=u;
    //////////////////
    for(j=head1[u];j!=-1;j=edge1[j].next)
    {
        v=edge1[j].to;
        if(visit[v]) LCA[edge1[j].num]=find(v);
    }
    //////////////////
    for(j=head[u];j!=-1;j=edge[j].next)
    {
        v=edge[j].to;
        if(!visit[v]) 
        {
            dis[v]=dis[u]+edge[j].val;
            tarjan(v);
            father[v]=u;
        }
    }
}
int main()
{
    int i,ncase,a,b,c;
    scanf("%d",&ncase);
    while(ncase--)
    {
        scanf("%d%d",&n,&m);
        tol=0;
        memset(head,-1,sizeof(head));
        for(i=1;i<n;i++)
        {
            scanf("%d%d%d",&a,&b,&c);
            add(a,b,c);
            add(b,a,c);
        }
        memset(visit,0,sizeof(visit));
        tol1=0;
        memset(head1,-1,sizeof(head1));
        for(i=1;i<=m;i++)
        {
            scanf("%d%d",&a,&b);
            add1(a,b,i);
            add1(b,a,i);
        }
        ///LCA是一种离线算法,所以刚开始需要把所有的询问都输入,然后用邻接表进行存储,i表示第i次询问
        dis[1]=0;
        tarjan(1);
        for(i=0;i<tol1;i+=2)
        {
            a=edge1[i].from;
            b=edge1[i].to;
            c=edge1[i].num;
            printf("%d\n",dis[a]+dis[b]-2*dis[LCA[c]]);
        }
    }
    return 0;
}

 

你可能感兴趣的:(tar)