C++之路进阶——LCA

1036 商务旅行

题目描述 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

思路:

裸lca。。。。,模板题。不懂看代码。

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cmath>
 4 #include<vector>
 5 #include<algorithm>
 6 #define maxn 30010
 7
 8 using namespace std;
 9
10 vector<int> s[30010];
11 int fa[maxn][100],deep[maxn],n,m;
12
13 void  getdeep(int k,int d)
14     {
15         deep[k]=d;
16         for (int i=1;(1<<i)<=deep[k];i++)
17           fa[k][i]=fa[fa[k][i-1]][i-1];
18         for (int i=0;i<s[k].size();i++)
19           {
20               if (!deep[s[k][i]])
21                  {
22                       fa[s[k][i]][0]=k;
23                       getdeep(s[k][i],d+1);
24                  }
25           }
26     }
27
28 int lca(int x,int y)
29   {
30       if (deep[x]<deep[y]) swap(x,y);
31       int t=deep[x]-deep[y];
32       for (int i=0;i<20;i++)
33        if ((1<<i)&t) x=fa[x][i];
34       for (int i=20;i>=0;i--)
35          {
36                if (fa[x][i]!=fa[y][i])
37                    {
38                          x=fa[x][i];
39                          y=fa[y][i];
40                    }
41          }
42     if (x==y)    return x;
43     return fa[x][0];
44   }
45
46 int main()
47   {
48       scanf("%d",&n);
49       for (int i=0;i<n-1;i++)
50         {
51             int x,y;
52             scanf("%d%d",&x,&y);
53             s[y].push_back(x);
54             s[x].push_back(y);
55         }
56     getdeep(1,1);
57     scanf("%d",&m);
58     int anss=0;
59     int a=1,b;
60     for (int i=0;i<m;i++)
61          {
62              scanf("%d",&b);
63               anss+=deep[a]+deep[b]-2*deep[lca(a,b)];
64               a=b;
65                  }
66     printf("%d",anss);
67     return 0;
68     }  
时间: 2024-07-28 22:51:24

C++之路进阶——LCA的相关文章

C++之路进阶——LCA(货车运输)

3287 货车运输 2013年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 q 辆货车在运输货物,司机们想知道每辆车在不超过车辆限重的情况下,最多能运多重的货物. 输入描述 Input Description 第一行有两个用一个空格隔开的整数 n,m,表示 A 国有 n 座城市和

UVA 11354 Bond 瓶颈路 最小生成树+LCA类似

题目链接:点击打开链接 题意: 给定n个点m条边的无向图 下面m行是(u,v) 和边权 下面q个询问 (u, v) 在这两个点间找一条路径使得这个路径上最大的边权最小. 数据保证询问的2个点之间一定存在路径 思路: 求瓶颈路,最小生成树跑一下. 然后求lca的代码里加入边权. 因为要使得最大的边权最小,所以用最小生成树的krusal算法, 正确性证明: 我们现在有联通块G,一个孤立点u,以及G与u之间的一些边,则显然我们选择边权最小的一条边把2个联通块连接. 这个过程就是krusal. #inc

C++之路进阶——最大流(紧急疏散)

3566 紧急疏散 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题目描述 Description 发生了火警,所有人员需要紧急疏散!假设每个房间是一个N M的矩形区域.每个格子如果是'.',那么表示这是一块空地:如果是'X',那么表示这是一面墙,如果是'D',那么表示这是一扇门,人们可以从这儿撤出房间.已知门一定在房间的边界上,并且边界上不会有空地.最初,每块空地上都有一个人,在疏散的时候,每一秒钟每个人都可以向上下左右四个方向移动一格,当然他也可以站着不动

C++之路进阶——最小费用最大流(善意的投票)

2879: [Noi2012]美食节 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 1304  Solved: 702[Submit][Status][Discuss] Description CZ市为了欢迎全国各地的同学,特地举办了一场盛大的美食节.作为一个喜欢尝鲜的美食客,小M自然不愿意错过这场盛宴.他很快就尝遍了美食节所有的美食.然而,尝鲜的欲望是难以满足的.尽管所有的菜品都很可口,厨师做菜的速度也很快,小M仍然觉得自己桌上没有已经摆在别人

C++之路进阶——最大流(善意的投票)

F.A.Qs Home Discuss ProblemSet Status Ranklist Contest ModifyUser  hyxzc Logout 捐赠本站 Notice:由于本OJ建立在Linux平台下,而许多题的数据在Windows下制作,请注意输入.输出语句及数据类型及范围,避免无谓的RE出现. 1934: [Shoi2007]Vote 善意的投票 Time Limit: 1 Sec  Memory Limit: 64 MBSubmit: 1646  Solved: 1006[

C++之路进阶——矩阵乘法(Xn数列)

1281 Xn数列 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 大师 Master 题目描述 Description 给你6个数,m, a, c, x0, n, g Xn+1 = ( aXn + c ) mod m,求Xn m, a, c, x0, n, g<=10^18 输入描述 Input Description 一行六个数 m, a, c, x0, n, g 输出描述 Output Description 输出一个数 Xn mod g 样例输入 Sample Inpu

C++之路进阶——最小费用最大流(支线剧情)

F.A.Qs Home Discuss ProblemSet Status Ranklist Contest ModifyUser  hyxzc Logout 捐赠本站 Notice:由于本OJ建立在Linux平台下,而许多题的数据在Windows下制作,请注意输入.输出语句及数据类型及范围,避免无谓的RE出现. 3876: [Ahoi2014]支线剧情 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 542  Solved: 332[Submit

c++之路进阶——treap树(普通平衡树)

4543 普通平衡树 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 大师 Master 题解 题目描述 Description 这是一道水题 顺便祝愿LEZ和ZQQ 省选AKAKAK 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:1. 插入x数2. 删除x数(若有多个相同的数,因只删除一个)3. 查询x数的排名(若有多个相同的数,因输出最小的排名)4. 查询排名为x的数5. 求x的前驱(前驱定义为小于x,且最大的数)6. 求x的后继(后继定义为大

c++之路进阶——块状链表(弹飞绵羊)

2333 弹飞绵羊 2010年省队选拔赛湖南 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 大师 Master 题解 题目描述 Description Lostmonkey发明了一种超级反弹装置.为了在绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏.游戏一开始,Lostmonkey在地上沿一条直线摆放 n个反弹装置,并按从前往后的方式将反弹装置依次编号为 0 到 n-1,对 0≤i≤n-1,为第 i 个反弹装置设定了初始弹力系数 ki,当绵羊落到第 i 个反弹装置上时,它将被往后