• 【9018:1893】牧场行走


    问题 C: 牧场行走

    时间限制: 1 Sec  内存限制: 128 MB
    提交: 74  解决: 36
    [提交][状态][讨论版]

    题目描述

    农场主奶牛有N个约翰,被标记为1到n,在同样被标记1到n的n块土地上吃草,第i头约翰在第i块牧场吃草。 这n块土地被n-1条路连接。 约翰可以在路上行走,第i条路连接第Ai,Bi块牧场,第i条路的长度是Li这些路被安排成任意两个约翰都可以通过这些路到达的情况,所以说这是一棵树。 这些约翰是非常喜欢交际的,经常会去互相访问,他们想让你去帮助他们计算Q对约翰之间的距离。

    输入

    第一行:两个被空格隔开的整数:N和Q

    第二行到第n行:第i+1行有两个被空格隔开的整数:Ai,Bi,Li

    第n+1行到n+Q行:每一行有两个空格隔开的整数:P1,P2,表示两头奶牛的编号。

    输出

    第1行到第Q行:每行输出一个数,表示那两头奶牛之间的距离。

    样例输入

    5 3
    2 1 1
    3 2 2
    4 1 4
    5 2 8
    3 4
    3 5
    4 5

    样例输出

    7
    10
    13

    提示

    2<=n,q<=1000

    题解:树上倍增lca,求树上两节点a、b的距离即为dis[a]+dis[b]-2*dis[lca(a,b)](其中dis表示该节点到根的距离)。

    代码如下:

     1 #include<iostream> 
     2 #include<cstdio> 
     3 #include<queue>
     4 #define maxpow 10 
     5 using namespace std;
     6 int n,p,fa[12][1005],dep[1005],dis[1005];
     7 int cnt,head[1005];
     8 bool vis[1005];
     9 struct edge{int to,next,val;}e[2005];
    10 void ins(int x,int y,int v){e[++cnt].to=y;e[cnt].next=head[x];head[x]=cnt;e[cnt].val=v;}
    11 void dfs(int u){
    12     vis[u]=true;
    13     for(int i=1;i<maxpow;i++)
    14         if(dep[u]<(1<<i)) break;
    15         else fa[i][u]=fa[i-1][fa[i-1][u]];//倍增操作 
    16     for(int i=head[u];i;i=e[i].next){
    17         int v=e[i].to;
    18         if(vis[v]) continue;
    19         dep[v]=dep[u]+1; dis[v]=dis[u]+e[i].val;
    20         fa[0][v]=u; dfs(v);
    21     }
    22 }
    23 int lca(int u,int v){
    24     if(dep[u]<dep[v]) swap(u,v);
    25     int dif=dep[u]-dep[v];
    26     for(int i=0;i<maxpow;i++) if((1<<i)&dif) u=fa[i][u];//u向上移动至于v同一深度 
    27     if(u==v) return u;
    28     for(int i=maxpow-1;i>=0;i--)
    29         if(fa[i][u]!=fa[i][v]){u=fa[i][u]; v=fa[i][v];}//u、v同时倍增 
    30     return fa[0][u];//注意这里返回fa 
    31 }
    32 int main()
    33 {
    34     scanf("%d%d",&n,&p);
    35     for(int i=1;i<n;i++){
    36         int x,y,l;
    37         scanf("%d%d%d",&x,&y,&l);
    38         ins(x,y,l); ins(y,x,l);
    39     }
    40     dfs(1);
    41     for(int i=1;i<=p;i++){
    42         int x,y; scanf("%d%d",&x,&y);
    43         printf("%d
    ",dis[x]+dis[y]-2*dis[lca(x,y)]);
    44     }
    45     return 0;
    46 }
  • 相关阅读:
    Inside Dynamics Axapta源代码赏析(五)
    Inside Dynamics Axapta源代码赏析(二)
    PHP查询显示关键字为红色
    textarea自适应高度
    背景图只显示一次,不循环,另外还有一个是PHP下的换行显示
    PHP格式化时间,形如(Wed 30,Jul 2008)
    实现页面加载中。。
    c++关于设置精度
    HDOJ 2662
    live Messenger
  • 原文地址:https://www.cnblogs.com/Beginner-/p/7467793.html
Copyright © 2020-2023  润新知