HDOJ2586 How far away ? #最近公共祖先 Tarjan离线算法#

How far away ?

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

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
 
Source
 
 
Recommend
 
lcy
 
Solution
 
#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef pair<int, int> q;
const int maxn = 4e4 + 10;
bool vis[maxn], root[maxn];
int ecnt, qcnt, ehead[maxn], qhead[maxn], pre[maxn], lca[maxn], dis[maxn];
struct edge { int to, dis, next; } edges[maxn << 1];
struct que { int id, to, next; } ques[maxn << 1];
vector<q> vec;

inline const 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 << 3) + (x << 1) + ch - '0'; ch = getchar(); }
    return x * f;
}

int Find(int id) { return pre[id] == id ? id : pre[id] = Find(pre[id]); }

void Union(int a, int b) { pre[Find(b)] = Find(a); }

void addEdge(int u, int v, int w)
{
    edges[ecnt].to = v;
    edges[ecnt].dis = w;
    edges[ecnt].next = ehead[u];
    ehead[u] = ecnt++;
}

void addQue(int id, int u, int v)
{
    ques[qcnt].id = id;
    ques[qcnt].to = v;
    ques[qcnt].next = qhead[u];
    qhead[u] = qcnt++;
}

void tarjan(int u)
{
    vis[u] = true;
    for (int i = ehead[u]; ~i; i = edges[i].next)
    {
        int v = edges[i].to, w = edges[i].dis;
        if (!vis[v])
        {
            dis[v] = dis[u] + w;
            tarjan(v);
            Union(u, v);
        }
    }
    for (int i = qhead[u]; ~i; i = ques[i].next)
    {
        int v = ques[i].to, id = ques[i].id;
        if (vis[v]) lca[id] = Find(v);
    }
}

int main()
{
    int t = read();
    while (t--)
    {
        vec.clear();
        ecnt = ecnt = 0;
        memset(vis, false, sizeof(vis));
        memset(ehead, -1, sizeof(ehead));
        memset(qhead, -1, sizeof(qhead));
        int n = read(), m = read();
        for (int i = 1; i <= n; i++)
        {
            pre[i] = i;
            root[i] = true;
        }
        for (int i = 0; i < n - 1; i++)
        {
            int u = read(), v = read(), w = read();
            root[v] = false;
            addEdge(u, v, w);
            addEdge(v, u, w);
        }
        for (int i = 0; i < m; i++)
        {
            int u = read(), v = read();
            addQue(i, u, v);
            addQue(i, v, u);
            vec.push_back(q(u, v));
        }
        for (int i = 1; i <= n; i++)
        {
            if (root[i])
            {
                dis[i] = 0;
                tarjan(i);
            }
        }
        for (int i = 0; i < (int)vec.size(); i++)
        {
            int u = vec[i].first, v = vec[i].second;
            printf("%d\n", dis[u] + dis[v] - dis[lca[i]] * 2);
        }
    }
    return 0;
}
发布了367 篇原创文章 · 获赞 148 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/qq_35850147/article/details/104098996