zoukankan      html  css  js  c++  java
  • ZOJ3195 Design the city(LCA)

    题目大概说给一棵树,每次询问三个点,问要把三个点连在一起的最少边权和是多少。

    分几种情况。。三个点LCA都相同,三个点有两对的LCA是某一点,三个点有两对的LCA各不相同。。。%……¥……

    画画图可以发现。。虽然好像不太严谨。。连接(a,b,c)三个点的最短边权和=(dist(a,b)+dist(b,c)+dist(a,c))/2,而dist(u,v)的计算可以预处理出各点到根的距离weight,dist(u,v)=weight(u)+weight(v)-2*weight(lca(u,v))。。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 using namespace std;
     5 #define MAXN 55555
     6 
     7 struct Edge{
     8     int v,w,next;
     9 }edge[MAXN<<1];
    10 int NE,head[MAXN];
    11 void addEdge(int u,int v,int w){
    12     edge[NE].v=v; edge[NE].w=w; edge[NE].next=head[u];
    13     head[u]=NE++;
    14 }
    15 
    16 int dep[MAXN],weight[MAXN],par[17][MAXN];
    17 void dfs(int u,int fa,int w){
    18     weight[u]=w;
    19     for(int i=head[u]; i!=-1; i=edge[i].next){
    20         int v=edge[i].v;
    21         if(v==fa) continue;
    22         dep[v]=dep[u]+1;
    23         par[0][v]=u;
    24         dfs(v,u,w+edge[i].w);
    25     }
    26 }
    27 
    28 void init(int n){
    29     dfs(0,0,0);
    30     for(int i=1; i<17; ++i){
    31         for(int j=0; j<n; ++j){
    32             if(par[i-1][j]==-1) continue;
    33             par[i][j]=par[i-1][par[i-1][j]];
    34         }
    35     }
    36 }
    37 
    38 int lca(int u,int v){
    39     if(dep[u]>dep[v]) swap(u,v);
    40     for(int k=0; k<17; ++k){
    41         if(dep[v]-dep[u]>>k&1){
    42             v=par[k][v];
    43         }
    44     }
    45     if(v==u) return u;
    46     for(int k=16; k>=0; --k){
    47         if(par[k][u]!=par[k][v]){
    48             u=par[k][u];
    49             v=par[k][v];
    50         }
    51     }
    52     return par[0][u];
    53 }
    54 
    55 int calc(int u,int v){
    56     return weight[u]+weight[v]-2*weight[lca(u,v)];
    57 }
    58 
    59 int main(){
    60     int n,q,a,b,c;
    61     bool flag=0;
    62     while(~scanf("%d",&n)){
    63         NE=0;
    64         memset(head,-1,sizeof(head));
    65         for(int i=1; i<n; ++i){
    66             scanf("%d%d%d",&a,&b,&c);
    67             addEdge(a,b,c);
    68             addEdge(b,a,c);
    69         }
    70 
    71         memset(par,-1,sizeof(par));
    72         init(n);
    73 
    74         if(flag) putchar('
    ');
    75         else flag=1;
    76         scanf("%d",&q);
    77         while(q--){
    78             scanf("%d%d%d",&a,&b,&c);
    79             printf("%d
    ",calc(a,b)+calc(b,c)+calc(a,c)>>1);
    80         }
    81     }
    82     return 0;
    83 }
  • 相关阅读:
    arcgis for flex 学习笔记(一)
    也说JS脚本加载控制
    数据验证随想(续)
    Oracle 脚本记录
    探讨:如何更快的赋值取值
    正则表达式技巧
    类似web风格的 Winform 分页控件
    数据验证随想
    [leetcode]Excel Sheet Column Title
    [leetcode]Merge k Sorted Lists
  • 原文地址:https://www.cnblogs.com/WABoss/p/5491998.html
Copyright © 2011-2022 走看看