hdu 2586 How far away ? 【图论-邻接表-图转树-Lca】

来源:互联网 发布:网络直播怎么下载 编辑:程序博客网 时间:2024/05/17 07:16
                                    How far away ? Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)

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

题目大意:一个村子里有n个房子,这n个房子用n-1条路连接起来,接下了有m次询问,每次询问两个房子a,b之间的距离是多少。
很明显的最近公共祖先问题,先建一棵树,然后求出每一点i到树根的距离dis[i],然后每次询问a,b之间的距离=dis[a]+dis[b]-2*dis[LCA(a,b)];
LCA(a,b)即是a,b的最近公共祖先。。

AC代码1:

# include <stdio.h># include <string.h># include <cmath># include <algorithm>using namespace std;# define MAXN 400005struct EDGE{    int v;    int w;    int next;}edge[MAXN]; //邻接表存放图结构int tot;int head[MAXN];int vis[MAXN];int pre[MAXN];int depth[MAXN];int dis[MAXN];int parent[MAXN][25];void Init(){    tot = 0;    memset(head, -1, sizeof(head));}void Addedge(int u, int v, int w){    edge[tot].v = v;    edge[tot].w = w;    edge[tot].next = head[u];    head[u] = tot++;}void dfs(int u, int father, int d) //搜索  把图结构装换成树结构{    depth[u] = d;    pre[u] = father;    for (int i = head[u]; i != -1; i = edge[i].next)    {        int v = edge[i].v;        if (v != father)        {            dis[v] = dis[u] + edge[i].w;            dfs(v, u,  d+1);        }    }}void LcaInit(int n){    int i, j;    for (j = 0; (1 << j) <= n; j++)    {        for (i = 1; i <= n; i++)        {            parent[i][j] = -1;        }    }    for (i = 1; i <= n; i++)    {        parent[i][0] = pre[i];    }    for (j = 1; (1 << j) <= n; j++)    {        for (i = 1; i <= n; i++)        {            if (parent[i][j - 1] != -1)            {                parent[i][j] = parent[parent[i][j - 1]][j - 1];            }        }    }}int Lca(int a, int b) //求公共祖先{    int i, j;    if (depth[a] < depth[b])    {        swap(a, b);    }    for (i = 0; (1 << i) <= depth[a]; i++);    i--;    for (j = i; j >= 0; j--)    {        if (depth[a] - depth[b] >= (1 << j))        {            a = parent[a][j];        }    }    if (a == b)    {        return a;    }    for (j = i; j >= 0; j--)    {        if (parent[a][j] != -1 && parent[a][j] != parent[b][j])        {            a = parent[a][j];            b = parent[b][j];        }    }    return pre[a];}int main(void){    int t;    int i, j;    scanf("%d", &t);    while (t--)    {        int n, m;        int u, v, w;        scanf("%d %d", &n, &m);        Init();        for (int i = 1; i < n; i++)        {            scanf("%d %d %d", &u, &v, &w);            Addedge(u, v, w);            Addedge(v, u, w);        }        dis[1] = 0;        dfs(1, -1, 0);        LcaInit(n);        int ans = 0;        for (i = 0; i < m; i++)        {            scanf("%d %d", &u, &v);            ans = dis[u] + dis[v] - 2 * dis[Lca(u, v)];            printf("%d\n", ans);        }    }    return 0;}

AC代码2:

# include <stdio.h># include <string.h># include <cmath># include <vector># include <algorithm>using namespace std;# define MAXN 40005struct node{    int v, w;    node(int a = 0, int b = 0){ v = a; w = b; }};vector<node> edge[MAXN];  //使用vector容器存放图结构int vis[MAXN];int pre[MAXN];int depth[MAXN];int dis[MAXN];int parent[MAXN][25];void dfs(int u, int father, int d) //图转树{    depth[u] = d;    pre[u] = father;    int num = edge[u].size();    for (int i = 0; i < num; i++)    {        int v = edge[u][i].v;        if (v != father)        {            dis[v] = dis[u] + edge[u][i].w;            dfs(v, u, d + 1);        }    }}void LcaInit(int n){    int i, j;    for (j = 0; (1 << j) <= n; j++)    {        for (i = 1; i <= n; i++)        {            parent[i][j] = -1;        }    }    for (i = 1; i <= n; i++)    {        parent[i][0] = pre[i];    }    for (j = 1; (1 << j) <= n; j++)    {        for (i = 1; i <= n; i++)        {            if (parent[i][j - 1] != -1)            {                parent[i][j] = parent[parent[i][j - 1]][j - 1];            }        }    }}int Lca(int a, int b){    int i, j;    if (depth[a] < depth[b])    {        swap(a, b);    }    for (i = 0; (1 << i) <= depth[a]; i++);    i--;    for (j = i; j >= 0; j--)    {        if (depth[a] - depth[b] >= (1 << j))        {            a = parent[a][j];        }    }    if (a == b)    {        return a;    }    for (j = i; j >= 0; j--)    {        if (parent[a][j] != -1 && parent[a][j] != parent[b][j])        {            a = parent[a][j];            b = parent[b][j];        }    }    return pre[a];}int main(void){    int t;    int i, j;    scanf("%d", &t);    while (t--)    {        int n, m;        int u, v, w;        scanf("%d %d", &n, &m);        for (i = 1; i <= n; i++)        {            edge[i].clear();        }        for (i = 1; i < n; i++)        {            scanf("%d %d %d", &u, &v, &w);            edge[u].push_back(node(v, w));            edge[v].push_back(node(u, w));        }        dis[1] = 0;        dfs(1, -1, 0);        LcaInit(n);        int ans = 0;        for (i = 0; i < m; i++)        {            scanf("%d %d", &u, &v);            ans = dis[u] + dis[v] - 2 * dis[Lca(u, v)];            printf("%d\n", ans);        }    }    return 0;}
0 0
原创粉丝点击