【codevs1036】商务旅行 LCA 倍增
1036 商务旅行
某首都城市的商人要经常到各城镇去做生意,他们按自己的路线去做,目的是为了更好的节约时间。
假设有N个城镇,首都编号为1,商人从首都出发,其他各城镇之间都有道路连接,任意两个城镇之间如果有直连道路,在他们之间行驶需要花费单位时间。该国公路网络发达,从首都出发能到达任意一个城镇,并且公路网络不会存在环。
你的任务是帮助该商人计算一下他的最短旅行时间。
输入文件中的第一行有一个整数N,1<=n<=30 000,为城镇的数目。下面N-1行,每行由两个整数a 和b (1<=a, b<=n; a<>b)组成,表示城镇a和城镇b有公路连接。在第N+1行为一个整数M,下面的M行,每行有该商人需要顺次经过的各城镇编号。
在输出文件中输出该商人旅行的最短时间。
5
1 2
1 5
3 5
4 5
4
1
3
2
5
7
题解:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 30005
using namespace std;
int n,m,city[maxn],ans,fist;
int tot,he[maxn],to[maxn*],ne[maxn*];
bool flag[maxn];
int f[][maxn],depth[maxn];
void add(int a,int b)
{
tot++;to[tot]=b;ne[tot]=he[a];he[a]=tot;
}
void build (int x)
{
for (int i=he[x];i;i=ne[i])
if (!flag[to[i]]){
flag[to[i]]=true;
depth[to[i]]=depth[x]+;
f[][to[i]]=x;
build(to[i]);
}
}
void bz()
{
for (int i=;i<=;i++)
for (int j=;j<=n;j++)
f[i][j]=f[i-][f[i-][j]];
}
int lca(int a,int b)
{
int mi=;
if (depth[a]<depth[b]) swap(a,b);
int derta=depth[a]-depth[b];
for (int i=;i<=;i++)
{
if (<<i & derta)
{
mi+=(<<i);
a=f[i][a];
}
}
if (a==b) return mi;
for (int i=;i>=;i--)
{
if (f[i][a]!=f[i][b]) {
a=f[i][a];
b=f[i][b];
int p=(<<i);p*=;//not mi+=(1<<i);mi*=2;
mi+=p;
}
}
a=f[][a];b=f[][b];
mi+=;
return mi;
}
int main()
{
freopen("codevs1036.in","r",stdin);
cin>>n;
for (int i=;i<n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
add(x,y);
add(y,x);
}
flag[]=true;
depth[]=;
build();
bz();
cin>>m;cin>>fist;
for (int i=;i<m;i++)
{
int x;scanf("%d",&x);
int y=lca(fist,x);
ans+=y;
fist=x;
}
cout<<ans<<endl;
return ;
}
借鉴方法:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 30005
using namespace std;
int n,m,city[maxn],ans,fist;
int tot,he[maxn],to[maxn*],ne[maxn*];
bool flag[maxn];
int f[][maxn],depth[maxn];
void add(int a,int b)
{
tot++;to[tot]=b;ne[tot]=he[a];he[a]=tot;
}
void build (int x)
{
for (int i=he[x];i;i=ne[i])
if (!flag[to[i]]){
flag[to[i]]=true;
depth[to[i]]=depth[x]+;
f[][to[i]]=x;
build(to[i]);
}
}
void bz()
{
for (int i=;i<=;i++)
for (int j=;j<=n;j++)
f[i][j]=f[i-][f[i-][j]];
}
int lca(int a,int b)
{
//int mi=0;
if (depth[a]<depth[b]) swap(a,b);
int derta=depth[a]-depth[b];
for (int i=;i<=;i++)
{
if (<<i & derta)
{
//mi+=(1<<i);
a=f[i][a];
}
}
if (a==b) return a;
for (int i=;i>=;i--)
{
if (f[i][a]==f[i][b]) continue;
else {
a=f[i][a];
b=f[i][b];
// mi+=(1<<i);mi=(mi<<1);
}
}
// a=f[0][a];b=f[0][b];
//mi+=2;
return f[][a];
}
int main()
{
freopen("codevs1036.in","r",stdin);
cin>>n;
for (int i=;i<n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
add(x,y);
add(y,x);
}
flag[]=true;
depth[]=;
build();
bz();
cin>>m;cin>>fist;
for (int i=;i<m;i++)
{
int x;scanf("%d",&x);
ans+=depth[fist]+depth[x]-*depth[lca(fist,x)];
fist=x;
}
cout<<ans<<endl;
return ;
}
【codevs1036】商务旅行 LCA 倍增的更多相关文章
- [codevs1036]商务旅行<LCA:tarjan&倍增>
题目链接:http://codevs.cn/problem/1036/ 今天翻箱倒柜的把这题翻出来做了,以前做的时候没怎么理解,所以今天来重做一下 这题是一个LCA裸题,基本上就把另一道裸题小机房的树 ...
- CodeVs.1036 商务旅行 ( LCA 最近公共祖先 )
CodeVs.1036 商务旅行 ( LCA 最近公共祖先 ) 题意分析 某首都城市的商人要经常到各城镇去做生意,他们按自己的路线去做,目的是为了更好的节约时间. 假设有N个城镇,首都编号为1,商人从 ...
- codevs1036商务旅行(LCA)
1036 商务旅行 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题解 题目描述 Description 某首都城市的商人要经常到各城镇去做 ...
- codevs 1036 商务旅行 (倍增LCA)
/* 在我还不知道LCA之前 暴力跑的SPFA 70分 三个点TLE */ #include<iostream> #include<cstdio> #include<cs ...
- [codevs1036] 商务旅行
题目描述 Description 某首都城市的商人要经常到各城镇去做生意,他们按自己的路线去做,目的是为了更好的节约时间. 假设有N个城镇,首都编号为1,商人从首都出发,其他各城镇之间都有道路连接,任 ...
- 倍增法-lca codevs 1036 商务旅行
codevs 1036 商务旅行 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description 某首都城市的商人要经常到各城镇去做生意 ...
- C++之路进阶——codevs1036(商务旅行)
1036 商务旅行 题目描述 Description 某首都城市的商人要经常到各城镇去做生意,他们按自己的路线去做,目的是为了更好的节约时间. 假设有N个城镇,首都编号为1,商人从首都出发,其他各城镇 ...
- 【codevs2370】小机房的树 LCA 倍增
2370 小机房的树 时间限制: 1 s 空间限制: 256000 KB 题目等级 : 钻石 Diamond 题目描述 Description 小机房有棵焕狗种的树,树上有N个节点,节点标号为0 ...
- LCA——倍增求解
LCA,即最近公共祖先,用于解决树上两点的最近公共祖先问题. ; lca(1,2)=3;(原谅我的绘画水平) LCA的求解有三种算法(我知道的)——tarjan,倍增,线段树(我只会两种),NOIp之 ...
随机推荐
- openfire升级指南
原文:http://www.liuhaihua.cn/archives/355.html 升级Openfire是和从头开始安装Openfire几乎一样简单.作为升级过程的一部分,它强烈建议您先备份当前 ...
- 激活MyEclipse 6.5方法-通过一段Java程序生成激活码
在MyEclipse中新建一个Java类,名为MyEclipseKeyGen,将下面的Java代码拷贝到MyEclipseKeyGen类中,先修改变量subscriber的值,然后运行程序即可获得Su ...
- $.each 与$().each()
在jquery中,遍历对象和数组,经常会用到$().each和$.each(),两个方法.两个方法是有区别的,从而这两个方法在针对不同的操作上,显示了各自的特点. $().each,对于这个方法,在d ...
- java 集合(List)
List: 特有的方法: 添加: add(int index, E element) addAll(int index, Collection<? extends E> c) 获取: ge ...
- JS预解析
1.在逐行读js代码前,解析器会先提取所有声明的var变量和函数 js解析器会先把脚本里所有var变量声明读一遍,但是它只读变量名字,不读变量值,一开始它会赋给所有读到的var变量一个[未定义]的值. ...
- db:seed 更好的生成测试数据
make:model -m -> 在database/migrations/目录下生成的table表中设置表的字段名和字段类型->在app/目录下对应的模型文件中设置可添加字段 -> ...
- 关于http响应内容压缩的一点小积累。
1.在tomcat的server.xml配置文件中,添加上背景颜色为绿色的配置,服务器就会自动压缩 <Connector port="80" maxHttpHeaderSiz ...
- append appendChild appendTo区别
1.append和appendChild的区别 append是jquery文档操作用法 ① append() 方法在被选元素的结尾(仍然在内部)插入指定内容. $(selector).append(c ...
- ccs6.0使用问题记录
ccs6.0使用问题记录 彭会锋 1 编译过程中提示warning " Description Resource Path Location Type #9-D nested commen ...
- 在Access中批量调用SQL语句
access的SQL视图一次只能执行一条SQL语句,那么在VBA中调用或许可以简便一些 例如: Public Sub 批量()Dim strsql As String strsql = " ...