题目链接: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. 使用纯粹的JS构建 Web Component

    原文链接:https://ayushgp.github.io/htm...译者:阿里云 - 也树 Web Component 出现有一阵子了. Google 费了很大力气去推动它更广泛的应用,但是除 ...

  2. JDBC概述及编程步骤详解

    目录 一.JDBC概述 二.JDBC编程步骤(以MySQL为例) 1.导入jar包 2.加载数据库驱动 3.通过DriverManager获得Connection对象 3.定义SQL语句 4.利用Co ...

  3. nowcoder 135F 圆

    链接:https://www.nowcoder.com/acm/contest/135/F来源:牛客网 圆(circle)   时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 3276 ...

  4. Spring Cloud Gateway 实现Token校验

    在我看来,在某些场景下,网关就像是一个公共方法,把项目中的都要用到的一些功能提出来,抽象成一个服务.比如,我们可以在业务网关上做日志收集.Token校验等等,当然这么理解很狭隘,因为网关的能力远不止如 ...

  5. (26)ASP.NET Core EF保存(基本保存、保存相关数据、级联删除、使用事务)

    1.简介 每个上下文实例都有一个ChangeTracker,它负责跟踪需要写入数据库的更改.更改实体类的实例时,这些更改会记录在ChangeTracker中,然后在调用SaveChanges时会被写入 ...

  6. deepin15.11安装N卡驱动,实测!!!(可解决N卡电脑关机卡屏)

    前言:deepin(深度)是一款由武汉深之度公司研发的一款适合国人日常学习的linux系统,其UI精美,美过Mac.它对于中国用户的一个亮点就是QQ微信等国软件傻瓜式安装(类似安卓应用商店安装),如果 ...

  7. JAVAEE学习day01

    1.二进制和十进制之间的转换: 十进制转换成二进制: 除2取余,从下往上吧余数拼接 二进制转换十进制: 1 0 1 0 8 4 2 1 把有1位的十进制求和 2.JAVA语言跨平台的原理 java程序 ...

  8. 面试官:HashMap死循环形成的原因是什么?

    介绍 HashMap实现原理 之前的文章已经分析了HashMap在JDK1.7的实现,这篇文章就只分析HashMap死循环形成的原因 死循环形成是在扩容转移元素的时候发生的 void resize(i ...

  9. npm run build时卡住不动了...

    在build文件夹里有个check-versions.js. if (shell.which('npm')) { versionRequirements.push({ name: 'npm', cur ...

  10. Element UI中的上传文件功能

    上传文件给后台: <el-upload style="display:inline-block" :limit=" class="upload-demo& ...