zoukankan      html  css  js  c++  java
  • Code[VS] 2370 LCA 题解

    Code[VS] 2370 小机房的树 题解

    题目描述 Description

    小机房有棵焕狗种的树,树上有N个节点,节点标号为0到N-1,有两只虫子名叫飘狗和大吉狗,分居在两个不同的节点上。有一天,他们想爬到一个节点上去搞基,但是作为两只虫子,他们不想花费太多精力。已知从某个节点爬到其父亲节点要花费 c 的能量(从父亲节点爬到此节点也相同),他们想找出一条花费精力最短的路,以使得搞基的时候精力旺盛,他们找到你要你设计一个程序来找到这条路,要求你告诉他们最少需要花费多少精力

    输入描述 Input Description
    第一行一个n,接下来n-1行每一行有三个整数u,v, c 。表示节点 u 爬到节点 v 需要花费 c 的精力。
    第n+1行有一个整数m表示有m次询问。接下来m行每一行有两个整数 u ,v 表示两只虫子所在的节点
    输出描述 Output Description

    一共有m行,每一行一个整数,表示对于该次询问所得出的最短距离。

    样例输入 Sample Input

    3

    1 0 1

    2 0 1

    3

    1 0

    2 0

    1 2

    样例输出 Sample Output

    1

    1

    2

    数据范围及提示 Data Size & Hint

    1<=n<=50000, 1<=m<=75000, 0<=c<=1000

    ———————————————————————————分割线—————————————————————————————

    分析:

    这道题是一个比较明显的求树上路径的题,显然

    Ans = dis[ u ] + dis[v] - 2*dis[ LCA( u , v ) ]   

    所以本题核心是求LCA ,将LCA问题转化为RMQ问题。这里使用线段树查询解决。

    代码&注释:

     

      1 /*
      2     LCA 
      3     author:SHHHS
      4     2016-09-26 02:25:19 
      5 */
      6 
      7 #include "bits/stdc++.h"
      8 
      9 using namespace std ;
     10 typedef long long QAQ ;
     11 struct Edge { int to , val , next ;};
     12 struct Tree { int l , r , mintr ,pos ;};
     13 int gmin ( int x , int y ) { return x > y ? y : x ;}
     14 int gmax ( int x , int y ) { return x < y ? y : x ;}
     15 const int maxN = 200010 ;
     16 const int INF = 2147483647 ;
     17 
     18 Tree tr[ maxN<<2 ] ;
     19 Edge e[ maxN ] ;
     20 int cnt , dfs_num=0 , min_val ,min_pos ;
     21 int head[maxN],fst[maxN],dep[maxN],ver[maxN],Dis[maxN];
     22 bool vis[maxN];
     23 
     24 inline void Add_Edge ( int x , int y , int _val ){
     25          e[ ++cnt ].to = y ;
     26          e[ cnt ].val = _val ;
     27          e[ cnt ].next = head[ x ] ;
     28          head[ x ] = cnt ;
     29 }
     30 
     31 void Build_Tree ( int x , int y , int i ) {
     32          tr[ i ].l = x ; tr[ i ].r = y ;
     33          if ( x==y ) tr[ i ].mintr = dep[ x ] , tr[ i ].pos = x ;
     34          else {
     35                   QAQ mid = ( tr[ i ].l + tr[ i ].r ) >>1 ;
     36                  Build_Tree ( x , mid , i<<1);
     37                  Build_Tree ( mid+1 , y , i<<1|1);
     38                  if (tr[i<<1].mintr > tr[i<<1|1].mintr )
     39                           tr[ i ].pos = tr[i<<1|1].pos,tr[ i ].mintr = tr[i<<1|1].mintr;
     40                  else 
     41                          tr[ i ].pos = tr[ i<<1 ].pos,tr[ i ].mintr = tr[ i<<1 ].mintr;
     42          }
     43          
     44 }
     45 
     46 void DFS ( int x , int depth ) {
     47          vis[ x ] = true ; 
     48          ver[ ++dfs_num ] = x ; 
     49          fst[ x ] = dfs_num ; 
     50          dep[ dfs_num ] = depth ;
     51          for ( int i=head[ x ] ; i ; i=e[i].next ) {
     52                   int temp = e[ i ].to ;
     53                   if ( !vis[ temp ] ){
     54                            Dis[ temp ] = Dis[ x ] + e[ i ].val ;
     55                            DFS ( temp , depth + 1 ) ;
     56                            ver[ ++dfs_num ] = x ; 
     57                            dep[ dfs_num ] = depth ;
     58                  }
     59          }
     60 }
     61 
     62 void Query_Min ( int q , int w , int i ) {
     63          if(q <= tr[i].l && w >= tr[i].r ){
     64                   if (tr[ i ].mintr < min_val ){
     65                            min_val = tr[i].mintr ;
     66                            min_pos = tr[i].pos ;
     67                   }
     68          }
     69          else {
     70                   QAQ mid = (tr[i].l + tr[i].r ) >> 1;
     71                   if(q > mid) {
     72                           Query_Min ( q , w , i << 1 | 1);
     73                   }
     74                   else if(w <= mid) {
     75                           Query_Min ( q , w , i << 1);
     76                   }
     77                   else {
     78                           Query_Min ( q , w , i << 1) ;
     79                           Query_Min ( q , w , i << 1 | 1);
     80                   }
     81          }
     82 }
     83 
     84 int LCA ( int x , int y ) {
     85          int px = fst[ x ] , py = fst[ y ] , tmp ;
     86          min_val = INF ;
     87          if ( py < px ) swap ( px , py ) ;
     88          Query_Min ( px , py , 1 ) ;
     89          return ver[ min_pos ] ;
     90 }
     91 int main ( ) {
     92          int N ,M ;
     93          scanf ("%d",&N);
     94          for ( int i=1 ; i<=N-1 ; ++i ) {
     95                   int _x , _y , __ ;
     96                   scanf("%d %d %d" , &_x , &_y ,&__ ) ;
     97                   ++_x;++_y;
     98                   Add_Edge ( _x , _y , __ ) ;
     99                   Add_Edge ( _y , _x , __ ) ;
    100          }
    101          DFS ( 1 , 1 ) ;
    102          Build_Tree ( 1 , dfs_num , 1 ) ;
    103          scanf ("%d",&M);
    104          for ( int i=1 ; i<=M ; ++i ) {
    105                   int u , v ;
    106                   scanf ( "%d%d" , &u , &v ) ;
    107                   ++u,++v;
    108                   printf ("%d",Dis[u]+Dis[v]-2*Dis[LCA ( u , v )] ) ;
    109                   putchar('
    ');
    110          }
    111          return 0 ;
    112 }

     

     1 /*
     2     树链剖分 
     3     author : SHHHS
     4     2016-9-28 14:41:17  
     5 */
     6 #include "bits/stdc++.h"
     7 
     8 using namespace std ;
     9 struct Edge { int to , next , val ;};
    10 const int maxN = 10010 ;
    11 const int INF = 2147483647 ;
    12 
    13 Edge e[ maxN ] ;
    14 int head[ maxN ], ind[ maxN ] ,start [ maxN ],pre[ maxN ],hv[maxN],DFN[maxN],Dis[maxN];
    15 
    16 int cnt , dfs_num ;
    17 
    18 void Add_Edge ( const int _x , const int _y , const int _val ) {
    19          e[ ++cnt ].to = _y ;
    20          e[ cnt ].val = _val ;
    21          e[ cnt ].next = head[ _x ] ;
    22          head[ _x ] = cnt ;
    23 }
    24 
    25 int Init_DFS ( const int x , const int father ) {
    26          int cnt_ , max_ = 0 ;
    27          for ( int i=head[ x ] ; i ; i=e[ i ].next ) {
    28                   int temp = e[ i ].to ;
    29                   if ( temp==father ) continue ;
    30                   Dis[ temp ] = Dis[ x ] + e[ i ] .val ;
    31                   int _ = Init_DFS ( temp , x ) ;
    32                  if ( _ > max_ ) {max_ = _ ; hv[ x ] = temp ;}
    33                  cnt_ +=_;
    34          }
    35          return cnt_ ;
    36 }
    37 
    38 void DFS ( const int x , const int father ) {
    39          if ( !start[ x ] ) start[ x ] = start[ father ] ;
    40          DFN[ x ] = ++dfs_num ;
    41          if ( hv[ x ] ) DFS ( hv[ x ] , x ) ;
    42          for ( int i=head[ x ] ; i ; i =e[ i ].next ) {
    43                   if ( e[ i ].to != hv[ x ] && e[i].to != father ) {
    44                            int temp = e[ i ].to ;
    45                            start[ temp ] = temp ;
    46                            pre [ temp ] = x ;
    47                            DFS ( temp , x ) ;
    48                   }
    49          }
    50 }
    51 
    52 int LCA ( const int x , const int y ) {
    53          int px = x , py = y ;
    54          while ( start[px]!=start[py] ) {
    55                   if ( DFN[start[px]]>DFN[start[py] ] ) {
    56                            px = pre[ start[px] ] ;
    57                   }
    58                   else {
    59                            py = pre[ start[py] ] ;
    60                   }
    61          }
    62          return DFN[px]>DFN[py]?py:px ;
    63 }
    64 void DEBUG_ ( int n ) {
    65          for ( int i=1 ; i<=n ; ++i ) {
    66                   printf ("%d:%d
    ",i,DFN[ i ] ) ;
    67          }
    68 }
    69 int main ( ) {
    70          int N , M ;
    71          scanf ( "%d" , &N ) ;
    72          for ( int i=1 ; i<=N-1 ; ++i ) {
    73                   int _x , _y ,_val ;
    74                   scanf ( "%d%d%d" ,&_x , &_y ,&_val ) ;
    75                   ++_x;++_y;
    76                   Add_Edge ( _x , _y , _val ) ;
    77                   Add_Edge ( _y , _x , _val ) ;
    78          }
    79 
    80          Init_DFS ( 1 , 1 ) ;
    81          start[ 1 ] = 1 ;
    82          DFS ( 1 , 1 ) ;
    83          
    84          //DEBUG_ ( N ) ;  
    85          
    86          scanf ( "%d" , &M ) ;
    87          for ( int i=1 ; i<=M ; ++i ) {
    88                   int u , v ;
    89                   scanf ( "%d%d" , &u , &v ) ;
    90                   ++u,++v;
    91                   printf ("%d
    ",Dis[ u ] + Dis[ v ] - 2*Dis[ LCA ( u , v ) ] ) ;
    92          }
    93          return 0 ;
    94 }     

     

     1 /*
     2      Tarjan LCA 
     3      author : SHHHS
     4      2016-10-09 13:10:32 
     5 */
     6 
     7 #include "cstdio"
     8 #include "cstring"
     9 #include "iostream"
    10 
    11 using namespace std ; 
    12 struct Edge {int to , next , val ; } ;
    13 struct Query { int u , v , next ; } ; 
    14 const int INF = 2147483647 ;
    15 const int maxN = 501000 ;
    16 
    17 Edge e[ maxN ] ;
    18 Query q[ maxN ] ;
    19 int head[ maxN ] , qead[ maxN ] , father[ maxN ] , Dis[ maxN ] , lca[ maxN ] ;
    20 bool vis[ maxN ] ;
    21 
    22 void Set_Init ( const int n ) {for ( int i=1 ; i<=n ; ++i ) father[ i ] = i ;}
    23 
    24 void Add_Edge ( int i , const int x , const int y , const int _val ) {
    25         e[ i ].to = y ;
    26         e[ i ].val = _val ;
    27         e[ i ].next = head[ x ] ;
    28         head[ x ] = i ;
    29 } 
    30 
    31 void Add_Query ( int i , const int x , const int y ) {
    32         q[ i ].u = x ;
    33         q[ i ].v = y ;
    34         q[ i ].next = qead[ x ] ;
    35         qead[ x ] = i ;
    36 }
    37 
    38 int getfa ( int x ) {
    39         return x==father[ x ] ? x : father[ x ] = getfa ( father[ x ] ) ;
    40 }
    41 
    42 void Tarjan ( int x ) {
    43         vis[ x ] = true ;
    44         for ( int i=head[ x ] ; i ; i = e[ i ].next ) {
    45                 int temp = e[ i ].to ;
    46                 if ( !vis[ temp ] ) {
    47                         Dis[ temp ] = Dis[ x ] + e[ i ].val ;
    48                         Tarjan ( temp ) ;
    49                         father[ temp ] = x ;
    50                 }
    51         }
    52         
    53         for ( int i=qead[ x ] ; i ; i = q[ i ].next ) {
    54                 int temp = q[ i ].u == x ? q[ i ].v : q[ i ].u ;
    55                 if ( vis[ temp ] )lca[ i >> 1 ] = getfa ( father[ temp ] ) ;
    56         }
    57 }
    58 
    59 int getDis(int i)
    60 {
    61     return Dis[ q [ i << 1 ].u ] + Dis[ q [ i << 1 ].v ] - 2 * Dis [ lca [ i ] ] ; 
    62 }
    63 void DEBUG_( int n  , int q ) {
    64         for ( int i=1 ; i<=n ; ++i ) printf ( "%d " , Dis[ i ] ) ;
    65         printf ( "
    " ) ;
    66         for ( int i=0 ; i<=q ; ++i ) printf ( "%d " , lca[ i ] ) ;
    67         printf ( "
    " ) ;
    68 }
    69 
    70 int main ( ) {
    71         int N , Q ;
    72         scanf ( "%d" , &N ) ;
    73         for ( int i=1 ; i<=N-1 ; ++i ) {
    74                 int _x , _y , _val ;
    75                 scanf ( "%d%d%d" , &_x , &_y , &_val ) ;
    76                 Add_Edge ( i << 1 , _x + 1 , _y + 1 , _val ) ;
    77                 Add_Edge ( i << 1 | 1 , _y + 1 , _x + 1 , _val ) ;
    78         }
    79         scanf ( "%d" , &Q ) ;
    80         for ( int i=1 ; i<=Q ; ++i ){
    81                 int _u , _v ;
    82                 scanf ( "%d%d" , &_u , &_v ) ;
    83                 Add_Query ( i << 1 , _u + 1 , _v + 1 ) ;
    84                 Add_Query ( i << 1 | 1 , _v + 1 , _u + 1 ) ;
    85         }
    86         Set_Init ( N ) ;
    87         Tarjan ( 1 ) ;
    88         //DEBUG_ ( N , Q ) ;
    89         for ( int i=1 ; i<=Q ; ++i ) {
    90                 printf ( "%d
    " , getDis ( i ) ) ;
    91         }
    92         return 0 ;
    93 }

    02:23:34 2016-09-26

    (完)

  • 相关阅读:
    【建兰普及模拟赛第一场】20181023
    【Uva11400 Lighting System Design】动态规划
    【洛谷 P2388 阶乘之乘】模拟
    【Uva1025 A Spy in the Metro】动态规划
    【洛谷P2028 龙兄摘苹果】动态规划
    【洛谷P1507 NASA的食物计划】动态规划
    【洛谷P1795 无穷的序列_NOI导刊2010提高(05)】模拟
    【洛谷P1281 书的复制】二分+动态规划
    【洛谷P4933 大师】动态规划
    「GXOI / GZOI2019」旧词
  • 原文地址:https://www.cnblogs.com/shadowland/p/5907779.html
Copyright © 2011-2022 走看看