【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之 ...
随机推荐
- 【Todo】Nginx架构学习
要进行Web服务,绕不开的就是Nginx.这已经是大型网站的标配.对Nginx进行一定程度的深入学习. http://www.ituring.com.cn/article/4436 http://bl ...
- hdu 1573 X问题
数论题,本想用中国剩余定理,可是取模的数之间不一定互质,用不了,看到网上有篇文章写得很好的:数论——中国剩余定理(互质与非互质),主要是采用合并方程的思想: 大致理解并参考他的代码后便去试试hdu上这 ...
- CSocket必须使用stream socket不能够使用数据报 socket
如果使用MFC socket类CSoket通讯,必须使用stream socket,不能够使用 SOCK_DGRAM 类型socket.原因如下: 1 stream socket和数据报socket的 ...
- android打开,保存图片到sd卡,显示图片
1.打开根目录下test.jpg Bitmap bm = BitmapFactory.decodeFile(Environment.getExternalStorageDirectory().getA ...
- 【Python】输出中文字符串的两种方法
print u"中文" # -*- coding: utf-8 -*- 这句话放在最上面,记得是最上面,顶格写 这样,print后,字符串前就不用加u了
- Windows不重启就使环境变量修改生效
以修改环境变量“PATH”为例,修改完成后,进入DOS命令提示符,输入:set PATH=C: ,关闭DOS窗口.再次打开DOS窗口,输入:echo %PATH% ,可以发现“我的电脑”->“属 ...
- iconv 文件编码相互转换
iconv 文件编码相互转换 示例: iconv -f utf-8 -t gbk ~/a.txt > ~/b.txt -f 从哪种格式转换 -t 要转换到哪种格式 a.txt要转换的文件 b.t ...
- ios使用webview浏览指定网页
#import "EDRViewController.h" @interface EDRViewController () @property(nonatomic,weak) UI ...
- mouseenter和mouseout中间的时间控制
为了防止鼠标快速滑过div而加的时间限制: 在看延迟绑定时候看到,这也算是延迟绑定了?:(20130909) <!DOCTYPE html> <html lang="en& ...
- Ubuntu配置Open BlockChain
/* 以前只是听说过BlockChain,没怎么了解过,最近导师在搞Blockchain,让我配一下Open BlockChain的环境,于是就硬着头皮配了一下,还挺顺利的. 由于没接触过BlockC ...