• hdoj 2586 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

     1 #include <stdio.h>
     2 #include <string.h>
     3 #include <iostream>
     4 using namespace std;
     5 
     6 int const MAX = 40005;
     7 
     8 struct Edge{
     9     int id, val; //当前边序号,边权
    10     int next;  //下一条
    11 }e[2 * MAX];
    12 
    13 int n, m, cnt;
    14 //x, y表示询问的起点和终点,z是x和y的LCA
    15 int x[MAX], y[MAX], z[MAX];
    16 //fa存祖先,dist存到根的距离,pre存父亲
    17 int fa[MAX], dist[MAX], pre[MAX];
    18 bool vis[MAX];
    19 
    20 void AddEdge(int u, int v, int w){
    21     e[cnt].id = u;
    22     e[cnt].val = w;
    23     e[cnt].next = pre[v];
    24     pre[v] = cnt++;
    25 
    26     e[cnt].id = v;
    27     e[cnt].val = w;
    28     e[cnt].next = pre[u];
    29     pre[u] = cnt++;
    30 }
    31 
    32 int Find(int x){
    33     return x == fa[x] ? x : fa[x] = Find(fa[x]);
    34 }
    35 
    36 void tarjan(int k){
    37     vis[k] = true;
    38     fa[k] = k;
    39     for(int i = 1; i <= m; i++){
    40         if(x[i] == k && vis[y[i]])
    41             z[i] = Find(y[i]);
    42         if(y[i] == k && vis[x[i]])
    43             z[i] = Find(x[i]);
    44     }
    45     for(int i = pre[k]; i != -1; i = e[i].next){
    46         if(!vis[e[i].id]){
    47             dist[e[i].id] = dist[k] + e[i].val;
    48             tarjan(e[i].id);
    49             fa[e[i].id] = k;
    50         }
    51     }
    52 }
    53 
    54 int main(){
    55     int T;
    56     scanf("%d",&T);
    57     while(T--){
    58         int u, v, w;
    59         scanf("%d %d", &n, &m);
    60         cnt = 0;
    61         memset(pre, -1, sizeof(pre));
    62         for(int i = 1; i < n; i++){
    63             scanf("%d %d %d", &u, &v, &w);
    64             AddEdge(u, v, w);
    65         }
    66         for(int i = 1; i <= n; i++)
    67             x[i] = y[i] = z[i] = 0;
    68         for(int i = 1; i <= m; i++){
    69             scanf("%d %d", &u, &v);
    70             x[i] = u;
    71             y[i] = v;
    72         }
    73         memset(vis, false, sizeof(vis));
    74         dist[1] = 0;
    75         tarjan(1);
    76         for(int i = 1; i <= m; i++)
    77             printf("%d
    ",dist[x[i]] + dist[y[i]] - 2 * dist[z[i]]);
    78     }
    79 }
     1 #include <iostream>
     2 #include <string.h>
     3 #include <stdio.h>
     4 const int N=40001;
     5 struct Edge{
     6     int v,w,next;
     7 }edge[2*N];     //每一条边要走两次,所以要是节点的两倍
     8 
     9 int n,m,size,head[N];
    10 int x[N],y[N],z[N],root[N],dis[N];
    11 bool mark[N];
    12 
    13 //插入边
    14 void Insert(int u,int v,int w){
    15     edge[size].v=v;edge[size].w=w;
    16     edge[size].next=head[u];head[u]=size++;
    17     edge[size].v=u;edge[size].w=w;
    18     edge[size].next=head[v];head[v]=size++;
    19 }
    20 //查找操作
    21 int Find(int x){
    22     if(root[x]!=x){
    23         return root[x]=Find(root[x]);
    24     }
    25     return root[x];
    26 }
    27 void LCA_Tarjan(int k){
    28     mark[k]=true;
    29     root[k]=k;
    30     for(int i=1;i<=m;i++){   //m次询问,z[i]保存的是点x[i]和y[i]最优公共祖先
    31         if(x[i]==k&&mark[y[i]])z[i]=Find(y[i]);  //z[i]=y[i];
    32         if(y[i]==k&&mark[x[i]])z[i]=Find(x[i]);  //z[i]=x[i]
    33     }
    34     for(int i=head[k];i!=-1;i=edge[i].next){
    35         if(!mark[edge[i].v]){
    36             dis[edge[i].v]=dis[k]+edge[i].w;
    37             LCA_Tarjan(edge[i].v);
    38             root[edge[i].v]=k;
    39         }
    40     }
    41 }
    42 int main(){
    43     int cas,u,v,w;
    44     scanf("%d",&cas);
    45     while(cas--){
    46         scanf("%d %d",&n, &m);
    47         size=0;
    48         memset(head,-1,sizeof(head));
    49         for(int i=1;i<n;i++){
    50             scanf("%d %d %d",&u, &v, &w);
    51             Insert(u, v, w);
    52         }
    53         for(int i=1;i<=n;i++){
    54             x[i]=y[i]=z[i]=0;
    55         }
    56         for(int i=1;i<=m;i++){
    57             scanf("%d %d", &u, &v);
    58             x[i]=u;y[i]=v;
    59         }
    60         memset(mark,false,sizeof(mark));
    61         dis[1]=0;
    62         LCA_Tarjan(1);
    63         for(int i=1;i<=m;i++)
    64             printf("%d
    ", dis[x[i]]+dis[y[i]]-2*dis[z[i]]);
    65     }
    66     return 0;
    67 }
  • 相关阅读:
    Redis单点登录
    MySQL有哪些存储引擎,各自的优缺点,应用场景
    MySQL慢查询优化、索引优化、以及表等优化总结
    Redis缓存和MySQL数据一致性方案详解
    Jenkies+github实现代码自动构建
    Python基础-day14-单元测试注册小例子
    Python基础-day13-unitest框架(Suite、runner)及生成报告,附带最新的HTMLTestRunnerNew.py文件
    Python基础-day11-继承和动态设置属性
    Python基础-day10-类的创建和调用
    Python基础-day03 字符串
  • 原文地址:https://www.cnblogs.com/z-712/p/7324122.html
Copyright © 2020-2023  润新知