zoukankan      html  css  js  c++  java
  • HDU 2586.How far away ?-在线LCA(ST)-代码很认真的写了注释(捞到变形)

    2018.9.10 0:40 重新敲一遍,然后很认真的写了注释,方便自己和队友看,刚过去的一天的下午打网络赛有一题用到了这个,但是没写注释,队友改板子有点伤,因为我没注释。。。

    以后写博客,代码要写注释,要把题目意思写上。。。

    我好捞啊。。。

     

     

    How far away ?

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


    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
     
     
    这个题就是求两点之间的最短距离,就是LCA模板题
     
     
    代码:
      1 //HDU2586
      2 #include<iostream>
      3 #include<cstdio>
      4 #include<cstring>
      5 #include<algorithm>
      6 #include<bitset>
      7 #include<cassert>
      8 #include<cctype>
      9 #include<cmath>
     10 #include<cstdlib>
     11 #include<ctime>
     12 #include<deque>
     13 #include<iomanip>
     14 #include<list>
     15 #include<map>
     16 #include<queue>
     17 #include<set>
     18 #include<stack>
     19 #include<vector>
     20 using namespace std;
     21 typedef long long ll;
     22 
     23 const double PI=acos(-1.0);
     24 const double eps=1e-6;
     25 const ll mod=1e9+7;
     26 const int inf=0x3f3f3f3f;
     27 const int maxn=4e4+10;
     28 const int maxm=100+10;
     29 #define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
     30 
     31 int dp[maxn<<1][25];//数组记得开2倍,因为遍历之后序列长度变为2*n-1
     32 bool vis[maxn];//标记
     33 
     34 struct node{
     35     int u,v,w,next;
     36 }edge[maxn<<1];
     37 
     38 int tot,head[maxn];//head保存的是以当前节点为起点的所有边中最后一条边的编号
     39 
     40 int num;
     41 
     42 inline void add(int u,int v,int w)
     43 {
     44     edge[num].u=u;edge[num].v=v;edge[num].w=w;//存边和权值
     45     edge[num].next=head[u];head[u]=num++;//next保存的是以u为起点的上一条边的编号
     46     u=u^v;v=u^v;u=u^v;//节点互换,存两次,因为为无向图,(u,v)存一次,(v,u)存一次,以下操作同上
     47     edge[num].u=u;edge[num].v=v;edge[num].w=w;
     48     edge[num].next=head[u];head[u]=num++;
     49 }
     50 
     51 int ver[maxn<<1],deep[maxn<<1],node[maxn<<1],dir[maxn<<1];
     52 //ver节点编号,dfs搜索过程中的序列,deep深度,node点编号位置,dir距离
     53 
     54 void dfs(int u,int dep)
     55 {
     56     vis[u]=true;//标记u节点被访问过
     57     ver[++tot]=u;//存dfs序
     58     node[u]=tot;//节点的dfs序的编号
     59     deep[tot]=dep;//该编号的深度
     60     for(int k=head[u];k!=-1;k=edge[k].next)//倒着遍历以u节点为起点的所有边的编号
     61     if(!vis[edge[k].v]){//如果该编号的边未被访问过
     62         int v=edge[k].v,w=edge[k].w;//v表示该边的终点,w表示该边的权值
     63         dir[v]=dir[u]+w;//权值和
     64         dfs(v,dep+1);//再往下dfsv节点的深度
     65         ver[++tot]=u;deep[tot]=dep;//表示dfs的时候还要回溯到上面,就是把dfs序保存一下,走到底再返回去去遍历没走过的点
     66     }
     67 }
     68 //可以看以前写的RMQ(ST)的详解https://www.cnblogs.com/ZERO-/p/8456910.html
     69 void ST(int n)//ST操作
     70 {
     71     for(int i=1;i<=n;i++)
     72         dp[i][0]=i;//初始化为自己
     73     for(int j=1;(1<<j)<=n;j++){
     74         for(int i=1;i+(1<<j)-1<=n;i++){
     75             int a=dp[i][j-1],b=dp[i+(1<<(j-1))][j-1];
     76             dp[i][j]=deep[a]<deep[b]?a:b;
     77         }
     78     }
     79 }
     80 
     81 int RMQ(int l,int r)
     82 {
     83     int k=0;
     84     while((1<<(k+1))<=r-l+1)k++;//最多能跳2的多少次幂
     85     int a=dp[l][k],b=dp[r-(1<<k)+1][k];//保存的是编号
     86     return deep[a]<deep[b]?a:b;
     87 }
     88 
     89 int LCA(int u,int v)
     90 {
     91     int x=node[u],y=node[v];
     92     if(x>y)swap(x,y);
     93     int res=RMQ(x,y);
     94     return ver[res];
     95 }
     96 
     97 int main()
     98 {
     99     int cas;
    100     scanf("%d",&cas);
    101     while(cas--){
    102         int n,q;
    103         num=0;
    104         scanf("%d%d",&n,&q);
    105         memset(head,-1,sizeof(head));//初始化
    106         memset(vis,false,sizeof(vis));
    107         for(int i=1;i<n;i++){
    108             int u,v,w;
    109             scanf("%d%d%d",&u,&v,&w);
    110             add(u,v,w);//存边
    111         }
    112         tot=0;dir[1]=0;
    113         dfs(1,1);
    114         ST(2*n-1);
    115         while(q--){
    116             int u,v;
    117             scanf("%d%d",&u,&v);
    118             int lca=LCA(u,v);
    119             printf("%d
    ",dir[u]+dir[v]-2*dir[lca]);//两点最短距离为每个点到根节点的距离-最近公共祖先到根节点的距离的*2
    120         }
    121     }
    122     return 0;
    123 }

    就这样,捞咸鱼。。。

    ༼༎ຶᴗ༎ຶ༽

  • 相关阅读:
    优启通(UEFI版)重装系统
    Beta阶段项目总结
    第二个阶段团队绩效管理
    第二阶段冲刺10天 第十天
    第二阶段冲刺10天 第九天
    第二阶段冲刺10天 第八天
    第二阶段冲刺10天 第七天
    第二阶段冲刺10天 第六天
    第二阶段冲刺10天 第五天
    第二阶段冲刺10天 第四天
  • 原文地址:https://www.cnblogs.com/ZERO-/p/9114403.html
Copyright © 2011-2022 走看看