题目链接:https://vijos.org/p/1460

    http://oj.fjaxyz.com:3389/problem.php?id=223

我不禁开始怀疑,这,真的是最近公共祖先的题吗,我是从一个讲解LCA的博客里找到这道题的,然后我就乖乖的用了可爱的LCA倍增,然后我就更加愉快的TLE了。

【思路】

判断u,v 的最近公共祖先是不是u,如果是,就加上这条路线。。。

判断u,v的最近公共祖先是不是u,TLE的代码是用倍增算法做的这个,但是啊,其实我们换一种说法就是判断u是不是v的祖先

那么这就简单了,想想LCA的离线做法tarjan,里面的dfn数组,储存的是i点的dfs序号,然后实质上其实是前序遍历序号

怎么判断u是v的祖先?刚刚才提到前序遍历,那我想想后序遍历,前序是根左右,后序是左右根,那么意思就是根在前序是比叶节点序号小,在后序是比叶节点序号大

于是我们储存数组begn[] ed[]储存点的前序序号和后序序号,如果begn[u]<begn[v]&&ed[u]>ed[v]说明u是v的祖先

解决了这个问题,接下来就是求距离,我们储存数组dis表示点i到根节点的距离,

所以u,v距离就是dis[u]+dis[v]-2*dis[lca(u,v)],由于这题满足条件是u为v的祖先,所以距离简化为dis[v]-dis[u]

LCA倍增算法

 #include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<stack>
#include<queue>
#include<cstdlib>
#define maxn 10005
#define ll long long
using namespace std; struct node{
int u,v;ll w;int nxt;
}e[maxn]; int head[maxn],n,m,f[maxn][];
ll dis[maxn],ans;
int cnt,vis[maxn],dep[maxn]; int tot;
void adde(int u,int v,int w){
e[tot]=(node){u,v,w,head[u]};
head[u]=tot;tot++;
} void build(int u){
for(int i=head[u];i!=-;i=e[i].nxt){
int v=e[i].v;
if(!vis[v]){
f[v][]=u;
dis[v]=dis[u]+e[i].w;
dep[v]=dep[u]+;
vis[v]=;
build(v);
}
}
} void first(){
for(int j=;j<=;j++){
for(int i=;i<=n;i++){
f[i][j]=f[f[i][j-]][j-];
}
}
} int up(int x,int d){
for(int i=;i<=d;i++)
x=f[x][];
return x;
} int find(int x,int y){
if(dep[x]<dep[y])swap(x,y);
if(dep[x]!=dep[y]){
int dd=dep[x]-dep[y];
x=up(x,dd);
}
if(x==y){return x;}
for(int j=;j>=;j--){
if(f[x][j]!=f[y][j]){
x=f[x][j];y=f[y][j];
}
}
return f[x][];
} ll len(int u,int v){
return dis[v]-dis[u];
} int main(){
memset(head,-,sizeof(head));
scanf("%d%d",&n,&m);
for(int i=;i<n;i++){
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
adde(u,v,w);
}
build();
first();
for(int i=;i<=m;i++){
int u,v;
scanf("%d%d",&u,&v);
int lca=find(u,v);
if(lca==u){ans+=len(u,v);cnt++;}
}
printf("%d\n%lld",cnt,ans);
}

倍增(TLE)

运用前序后序的dfs算法

 #include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<stack>
#include<queue>
#include<cstdlib>
#define maxn 10005
using namespace std; struct node{
int u,v;long long w;int nxt;
}e[maxn]; int head[maxn],n,m;
int cnt,vis[maxn];
int begn[maxn],ed[maxn];
long long ans,dis[maxn]; int tot;
void adde(int u,int v,long long w){
e[tot]=(node){u,v,w,head[u]};
head[u]=tot;tot++;
} int num,hehe;
void build(int u){
num++;begn[u]=num;
for(int i=head[u];i!=-;i=e[i].nxt){
int v=e[i].v;
if(!vis[v]){;
dis[v]=dis[u]+e[i].w;
vis[v]=;
build(v);
}
}
hehe++;ed[u]=hehe;
} int main(){
memset(head,-,sizeof(head));
scanf("%d%d",&n,&m);
for(int i=;i<n;i++){
int u,v;long long w;
scanf("%d%d%lld",&u,&v,&w);
adde(u,v,w);
}
build();
for(int i=;i<=m;i++){
int u,v;
scanf("%d%d",&u,&v);
if(begn[u]<=begn[v]&&ed[u]>=ed[v]){
ans+=dis[v]-dis[u];cnt++;
}
}
printf("%d\n%lld",cnt,ans);
}

AC于vijos

然后问题就来了,这个在vijos上AC的代码在meto code上还是WA了,我已经放弃了,因为meto code不提供错误数据也不告诉我错了几组,所以我最终还是没有在meto code上成功

[vijos1460&Metocode P223]拉力赛<LCA>的更多相关文章

  1. 算法笔记--lca倍增算法

    算法笔记 模板: vector<int>g[N]; vector<int>edge[N]; ][N]; int deep[N]; int h[N]; void dfs(int ...

  2. 最近公共祖先LCA(Tarjan算法)的思考和算法实现

    LCA 最近公共祖先 Tarjan(离线)算法的基本思路及其算法实现 小广告:METO CODE 安溪一中信息学在线评测系统(OJ) //由于这是第一篇博客..有点瑕疵...比如我把false写成了f ...

  3. lca(最近公共祖先(离线))

    转自大佬博客 : https://www.cnblogs.com/JVxie/p/4854719.html   LCA 最近公共祖先 Tarjan(离线)算法的基本思路及其算法实现 首先是最近公共祖先 ...

  4. Vijos——T1406 拉力赛

    https://vijos.org/p/1460 描述 车展结束后,游乐园决定举办一次盛大的山道拉力赛,平平和韵韵自然也要来参加大赛. 赛场上共有n个连通的计时点,n-1条赛道(构成了一棵树).每个计 ...

  5. 最近公共祖先LCA(Tarjan算法)的思考和算法实现——转载自Vendetta Blogs

    LCA 最近公共祖先 Tarjan(离线)算法的基本思路及其算法实现 小广告:METO CODE 安溪一中信息学在线评测系统(OJ) //由于这是第一篇博客..有点瑕疵...比如我把false写成了f ...

  6. LCA 最近公共祖先 Tarjan(离线)算法的基本思路及其算法实现

    首先是最近公共祖先的概念(什么是最近公共祖先?): 在一棵没有环的树上,每个节点肯定有其父亲节点和祖先节点,而最近公共祖先,就是两个节点在这棵树上深度最大的公共的祖先节点. 换句话说,就是两个点在这棵 ...

  7. 【模板】Tarjian求LCA

    概念 公共祖先,就是两个节点在这棵树上深度最大的公共的祖先节点 举个例子吧,如下图所示4和5的最近公共祖先是2,5和3的最近公共祖先是1,2和1的最近公共祖先是1. 算法 常用的求LCA的算法有:Ta ...

  8. BZOJ 3083: 遥远的国度 [树链剖分 DFS序 LCA]

    3083: 遥远的国度 Time Limit: 10 Sec  Memory Limit: 1280 MBSubmit: 3127  Solved: 795[Submit][Status][Discu ...

  9. BZOJ 3626: [LNOI2014]LCA [树链剖分 离线|主席树]

    3626: [LNOI2014]LCA Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 2050  Solved: 817[Submit][Status ...

随机推荐

  1. 集成google翻译的小tips

    文章首发于github.io 2018-08-04 12:43:20 google翻译的强大,就像我们公司的slogan : "让语言无国界,让世人心相通" 友情提示: googl ...

  2. 支持IE6、IE7、IE8等低端浏览器的简化版vue

    最近研究Vue的底层原理,写了一个简化版的Vue,可以在支持IE6.IE7.IE8等低端浏览器运行.由于低端浏览器不支持对象属性定义,所以设置属性不支持直接赋值,需要调用虚拟机实例的set方法.目前只 ...

  3. python3 flask shell

    python shell来操作flask flask shell 报错: from flask_bootstrap import BootstrapImportError: No module nam ...

  4. python正则表达式之re模块使用

    python第一个正则表达式 https://www.imooc.com/learn/550 r'imooc'  Pattern Match result In [2]: import re In [ ...

  5. python自动化第二课 - python基础

    1.标识符(identitifier),识别身份 定义:在编程语言中,标识符就是用户编程时使用的名字,用于给变量.常量.函数.语句块等命名 标识符命令规范: 1)英文,数字以及下划线(_)但不能以数字 ...

  6. java算法--普通队列

    数据结构队列 首先明确一下队列的概念. 队列是一种有序列表,使用数组的结构来存储队列的数据. 队列是一种先进先出的算法.由前端加入,由后端输出. 如下图: ​ 第一个图 第二个图 第三个图 这就是队列 ...

  7. Python模块二

    os模块是与操作系统交互的一个接口​ <em>#和文件夹相关 os.makedirs('dirname1/dirname2')    可生成多层递归目录 os.removedirs('di ...

  8. WINDOWS上JDK安装与环境变量设置

    一.JDK安装 jdk版本:jdk1.8.0_144 下载链接:https://pan.baidu.com/s/1eS2bFhg 密码:e3q1 下载JDK后点击安装,可以根据需要修改JDK的安装目录 ...

  9. js 实现简单的选项卡

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  10. Markdown试用

    目录 今天又是充满希望的一天 一.是什么 二.为什么 三.怎么做 代码 这世界上好人坏人都很多,我不是一个坏人. 我不是个英雄,我只是个拿