zoukankan      html  css  js  c++  java
  • 2017.10.24:lca专题系列

    商务旅行
    题目描述 Description

    某首都城市的商人要经常到各城镇去做生意,他们按自己的路线去做,目的是为了更好的节约时间。

    假设有N个城镇,首都编号为1,商人从首都出发,其他各城镇之间都有道路连接,任意两个城镇之间如果有直连道路,在他们之间行驶需要花费单位时间。该国公路网络发达,从首都出发能到达任意一个城镇,并且公路网络不会存在环。

    你的任务是帮助该商人计算一下他的最短旅行时间。

    输入描述 Input Description

    输入文件中的第一行有一个整数N,1<=n<=30 000,为城镇的数目。下面N-1行,每行由两个整数a 和b (1<=ab<=n; a<>b)组成,表示城镇a和城镇b有公路连接。在第N+1行为一个整数M,下面的M行,每行有该商人需要顺次经过的各城镇编号。

    输出描述 Output Description

        在输出文件中输出该商人旅行的最短时间。

    样例输入 Sample Input
    5
    1 2
    1 5
    3 5
    4 5
    4
    1
    3
    2
    5
    样例输出 Sample Output

    7

    题解

    每两个点之间计算路径长度,累加答案即可。

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cstring>
     4 #define maxn 30005
     5 using namespace std;
     6 int n,m,head[maxn],ecnt,fa[maxn],siz[maxn],deep[maxn],son[maxn],top[maxn],ans;
     7 struct edge{
     8     int v,next;
     9 }E[maxn<<1];
    10 void add(int u,int v)
    11 {
    12     E[++ecnt].v=v;
    13     E[ecnt].next=head[u];
    14     head[u]=ecnt;
    15 }
    16 void dfs(int x)
    17 {
    18     siz[x]=1;
    19     for(int i=head[x] ; i ; i=E[i].next )
    20     {
    21         int v=E[i].v;
    22         if(fa[x]==v)continue;
    23         fa[v]=x;deep[v]=deep[x]+1;
    24         dfs(v);
    25         siz[x]+=siz[v];
    26         if(siz[son[x]]<siz[v])son[x]=v;
    27     }
    28 }
    29 void dfs2(int x,int tp)
    30 {
    31     top[x]=tp;
    32     if(son[x])dfs2(son[x],tp);
    33     for(int i=head[x]; i ; i=E[i].next )
    34     {
    35         int v=E[i].v;
    36         if(son[x]==v||fa[x]==v)continue;
    37         dfs2(v,v);    
    38     }    
    39 } 
    40 int lca(int x,int y)
    41 {
    42     while(top[x]!=top[y])
    43     {
    44         if(deep[top[x]]<deep[top[y]])swap(x,y);
    45         x=fa[top[x]];
    46     }
    47     return deep[x]<deep[y]?x:y;
    48 }
    49 
    50 int main()
    51 {
    52     int u,v,tmp,a;
    53     scanf("%d",&n);
    54     for(int i=1 ; i<n ; ++i )
    55     {
    56         scanf("%d%d",&u,&v);
    57         add(u,v);add(v,u);
    58     }
    59     dfs(1);dfs2(1,1);
    60     scanf("%d",&m);
    61     scanf("%d",&tmp);
    62     for(int i=2 ; i<=m ; ++i )
    63     {
    64         scanf("%d",&a);
    65         ans+=deep[tmp]+deep[a]-deep[lca(tmp,a)]*2;
    66         tmp=a;
    67     }
    68     printf("%d",ans);
    69     return 0;
    70 }

     bzoj1787:[Ahoi2008]Meet 紧急集合

    Input

    Output

    题解

    三个点求lca???不存在的

    画个图看一看,不难发现,三点间两两求lca总会有两个lca相同,而且三点到那个lca的距离大于到另外一个lca的距离。

    分情况判断就行了

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cstring>
     4 #define maxn 500005
     5 using namespace std;
     6 int ecnt,head[maxn],siz[maxn],son[maxn],deep[maxn],fa[maxn],top[maxn],n,m;
     7 struct edge{
     8     int v,next;
     9 }E[maxn<<1];
    10 void add(int u,int v)
    11 {
    12     E[++ecnt].v=v;
    13     E[ecnt].next=head[u];
    14     head[u]=ecnt;
    15 }
    16 void dfs(int x)
    17 {
    18     siz[x]=1;
    19     for(int i=head[x] ; i ; i=E[i].next )
    20     {
    21         int v=E[i].v;
    22         if(fa[x]==v)continue;
    23         deep[v]=deep[x]+1;fa[v]=x;
    24         dfs(v);
    25         siz[x]+=siz[v];
    26         if(siz[son[x]]<siz[v])son[x]=v; 
    27     }
    28 }
    29 void dfs2(int x,int tp)
    30 {
    31     top[x]=tp;
    32     if(son[x])dfs2(son[x],tp);
    33     for(int i=head[x] ; i ; i=E[i].next )
    34     {
    35         int v=E[i].v;
    36         if(son[x]==v||fa[x]==v)continue;
    37         dfs2(v,v);    
    38     } 
    39 }
    40 int lca(int x,int y)
    41 {
    42     while(top[x]!=top[y])
    43     {
    44         if(deep[top[x]]<deep[top[y]])swap(x,y);
    45         x=fa[top[x]];
    46     }
    47     return deep[x]<deep[y]?x:y;
    48 }
    49 inline int read()
    50 {
    51     int ret(0);
    52     char ch=getchar();
    53     while(ch>'9'||ch<'0')ch=getchar();
    54     while(ch>='0'&&ch<='9')
    55     {
    56         ret=(ret<<1)+(ret<<3)+ch-'0';
    57         ch=getchar();
    58     }
    59     return ret;
    60 }
    61 int main()
    62 {
    63     int u,v,a,b,c,t1,t2,t3,jud,tmp,fu;
    64     n=read();m=read();
    65     for(int i=1 ; i<n ; ++i )
    66     {
    67         u=read();v=read();
    68         add(u,v);add(v,u);
    69     }
    70     dfs(1);dfs2(1,1);
    71     while(m--)
    72     {
    73         a=read();b=read();c=read();
    74         t1=lca(a,b);t2=lca(a,c);t3=lca(b,c);
    75         if(t1==t2)
    76         {
    77             fu=t3;
    78             jud=lca(t3,a);
    79             tmp=deep[b]+deep[c]+deep[a]-deep[t3]-deep[jud]*2;
    80         }
    81         if(t2==t3)
    82         {
    83             fu=t1;
    84             jud=lca(t1,c);
    85             tmp=deep[b]+deep[c]+deep[a]-deep[t1]-deep[jud]*2;
    86         }
    87         if(t1==t3)
    88         {
    89             fu=t2;
    90             jud=lca(t2,b);
    91             tmp=deep[b]+deep[c]+deep[a]-deep[t2]-deep[jud]*2;
    92         }
    93         printf("%d %d
    ",fu,tmp);
    94     }
    95     return 0;
    96 }
  • 相关阅读:
    现代软件工程的构建之法
    How do I Check for Duplicate Items in a ListView?
    (转)aspxgridview记录的批量修改
    vs2010简体中文旗舰版智能感知,中文提示,英文提示变化的问题
    (转)怎样成为一名Android开发者
    It’s Not Too Late to Learn How to Code
    (转)手机屏幕VGA QVGA HVGA WVGA区别
    (转)CodeSmithSchemaExplorer类结构详细介绍
    (转)C#控件命名规范
    DataReader 绑定DataGridView的方式
  • 原文地址:https://www.cnblogs.com/fujudge/p/7725638.html
Copyright © 2011-2022 走看看