2017.10.24:lca专题系列

Posted fujudge

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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\\n",fu,tmp);
94     }
95     return 0;
96 }

 

以上是关于2017.10.24:lca专题系列的主要内容,如果未能解决你的问题,请参考以下文章

2017.10.24

专题训练之LCA

空间谱专题16:信号个数估计

开篇│“提升代码质量”专题系列——证券软件总部持续推进质量提升计划

Tarjan 算法求 LCA / Tarjan 算法求强连通分量

Java技术专题「原理分析系列」分析反射底层原理及基础开发实战