HDU2586How far away ?(LCA-在线ST+ tarjan离线)

How far away ?

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


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
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
题目就是问任意两个房子之间的最短路径长。
用LCA算出最近公共祖先t,长度就是dis[u]+dis[v]-2*dis[t].

LCA-ST

```
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cctype>
#include<cmath>
#include<ctime>
#include<string>
#include<stack>
#include<deque>
#include<queue>
#include<list>
#include<set>
#include<map>
#include<cstdio>
#include<limits.h>
#define MOD 1000000007
#define fir first
#define sec second
#define fin freopen("/home/ostreambaba/文档/input.txt", "r", stdin)
#define fout freopen("/home/ostreambaba/文档/output.txt", "w", stdout)
#define mes(x, m) memset(x, m, sizeof(x))
#define Pii pair<int, int>
#define Pll pair<ll, ll>
#define INF 1e9+7
#define inf 0x3f3f3f3f
#define Pi 4.0*atan(1.0)

#define lowbit(x) (x&(-x))
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1

typedef long long ll;
typedef unsigned long long ull;
const double eps = 1e-9;
const int maxn = 4*1e4+10;
using namespace std;

inline int read(){
    int x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
    return x*f;
}
//ver:节点编号 R:深度 first:点编号第一次位置 dir:距离
int dp[20][maxn<<1],to;
int tot,ver[maxn<<1],head[maxn],first[maxn],dep[maxn<<1],dir[maxn],vis[maxn];
struct edge{
    int v,w,next;
}g[maxn<<1];
void init(){
    tot=0;
    to=0;
    mes(head,-1);
    mes(vis,false);
}
inline void addEdge(int u,int v,int w){
    g[to].v=v;
    g[to].w=w;
    g[to].next=head[u];
    head[u]=to++;
}
void dfs(int u,int dt){
    vis[u]=true;
    ver[++tot]=u;
    first[u]=tot;
    dep[tot]=dt;
    for(int i=head[u];~i;i=g[i].next){
        if(!vis[g[i].v]){
            int v=g[i].v,w=g[i].w;
            dir[v]=dir[u]+w;
            dfs(v,dt+1);
            ver[++tot]=u;
            dep[tot]=dt;
        }
    }
}
void rmq(int N,int limits){
    for(int i=1;i<=N;++i){
        dp[0][i]=i;
    }
    for(int i=1;i<=limits;++i){
        for(int j=1;j<=N;++j){
            if(j+(1<<i)-1<=N){
                int a=dp[i-1][j],b=dp[i-1][j+(1<<i>>1)];
                dp[i][j]=(dep[a]<dep[b]?a:b);
            }
        }
    }
}
inline int query(int l,int r){
    int k=floor(log2(r-l+1));
    int a=dp[k][l],b=dp[k][r-(1<<k)+1];
    return dep[a]<dep[b]?a:b;
}
int LCA(int u,int v){
    int x=first[u],y=first[v];
    if(x>y){
        swap(x,y);
    }
    int res=query(x,y);
    return ver[res];
}
int main(){
    //freopen("/home/ostreambaba/文档/input.txt", "r", stdin);
    //freopen("/home/ostreambaba/文档/output.txt", "w", stdout);
    int t=read();
    while(t--){
        init();
        int n,m;
        n=read(),m=read();
        for(int i=0;i<n-1;++i){
            int u,v,w;
            u=read(),v=read(),w=read();
            addEdge(u,v,w);
            addEdge(v,u,w);
        }
        dfs(1,1);
        dir[1]=0;
        rmq(2*n-1,(log2(2*n-1)+1));
        while(m--){
            int u,v;
            u=read(),v=read();
            int t=LCA(u,v);
            //cout<<"lca:"<<t<<endl;
            printf("%d\n",dir[u]+dir[v]-dir[t]*2);
        }
    }
    return 0;
}
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cctype>
#include<cmath>
#include<ctime>
#include<string>
#include<stack>
#include<deque>
#include<queue>
#include<list>
#include<set>
#include<map>
#include<cstdio>
#include<limits.h>
#define MOD 1000000007
#define fir first
#define sec second
#define fin freopen("/home/ostreambaba/文档/input.txt", "r", stdin)
#define fout freopen("/home/ostreambaba/文档/output.txt", "w", stdout)
#define mes(x, m) memset(x, m, sizeof(x))
#define Pii pair<int, int>
#define Pll pair<ll, ll>
#define INF 1e9+7
#define inf 0x3f3f3f3f
#define Pi 4.0*atan(1.0)

#define lowbit(x) (x&(-x))
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1

typedef long long ll;
typedef unsigned long long ull;
const double eps = 1e-9;
const int maxn = 4*1e4+10;
const int maxm = 205;
using namespace std;

inline int read(){
    int x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
    return x*f;
}
struct edge{
    int u,v,w,next;
};
struct qedge{
    int u,v,idx,next;
};
edge g[maxn<<1];
qedge q[maxm<<1];
int p[maxn],tot,to,head[maxn],qhead[maxn],vis[maxn],dis[maxn],lca[maxm<<1];
void init(){
    tot=to=0;
    mes(head,-1);
    mes(vis,false);
    mes(qhead,-1);
}
inline void addEdge(int u,int v,int w){
    g[tot].v=v;
    g[tot].w=w;
    g[tot].next=head[u];
    head[u]=tot++;
}
inline void addQEdge(int u,int v,int w){
    q[to].u=u;
    q[to].v=v;
    q[to].idx=w;
    q[to].next=qhead[u];
    qhead[u]=to++;
}
inline int find(int x){
    return x==p[x]?x:p[x]=find(p[x]);
}
inline void merge(int x,int y){
    x=find(x),y=find(y);
    if(x!=y){
        p[y]=x;
    }
}
void tarjan(int u){
    vis[u]=true;

    for(int i=head[u];~i;i=g[i].next){ 
        int v=g[i].v,w=g[i].w;
        if(!vis[v]){
            dis[v]=dis[u]+w;
            tarjan(v);
            p[v]=u;
        }
    }

    for(int i=qhead[u];~i;i=q[i].next){ //写成head[u],尴尬一直wa
        int v=q[i].v;
        if(vis[v]){
            lca[q[i].idx]=find(v);
        }
    }
}
int main(){
    //freopen("/home/ostreambaba/文档/input.txt", "r", stdin);
    //freopen("/home/ostreambaba/文档/output.txt", "w", stdout);
    int t=read();
    while(t--){
        init();
        int n,m;
        int u,v,w;
        tot=0;
        n=read(),m=read();
        for(int i=1;i<=n;++i){
            p[i]=i;
        }
        for(int i=0;i<n-1;++i){
            scanf("%d%d%d",&u,&v,&w);
            addEdge(u,v,w);
            addEdge(v,u,w);
        }
        to=0;
        for(int i=1;i<=m;++i){
            scanf("%d%d",&u,&v);
            addQEdge(u,v,i);
            addQEdge(v,u,i);
        }
        dis[1]=0;
        tarjan(1);
        for(int i=0;i<to;i+=2){
            printf("%d\n",dis[q[i].u]+dis[q[i].v]-2*dis[lca[q[i].idx]]);
            //cout<<q[i].u<<" "<<q[i].v<<" "<<lca[q[i].idx]<<endl;
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/viscu/article/details/70141399