简述这几天的LCA 心得:

LCA有两种做法:离线 or 在线

先学的离线;

原理博客很多。

我写得两道题,已经模板。

HDU:http://acm.hdu.edu.cn/showproblem.php?pid=2586

HDU :http://acm.hdu.edu.cn/showproblem.php?pid=2874 2874;

之前一份板子:

 #pragma comment(linker, "/STACK:10240000000,10240000000")  

 #include<iostream>
#include<stdio.h>
#include<string.h>
#include<cmath>
#include<algorithm>
#include<string>
#include<vector>
using namespace std; #define N 51111
struct node
{
int v,w; node(int vv,int ww)
{
v=vv;
w=ww;
}
};
int f[N],dis[N],ans[N],vis[N],n;
vector<node>mp[N];
vector<node>q[N]; int find(int x)
{
if (f[x]!=x) f[x]=find(f[x]);
return f[x];
} void lca(int u)
{
for (int i=;i<mp[u].size();i++)
{
int v=mp[u][i].v;
if (vis[v]) continue;
vis[v]=; dis[v]=dis[u]+mp[u][i].w;
lca(v);
f[v]=u;
for (int j=;j<q[v].size();j++)
{
int c=q[v][j].v;
if (vis[c]&&ans[q[v][j].w]==-)
{
if (v==c) ans[q[v][j].w]=;
else ans[q[v][j].w]=dis[v]+dis[c]-*dis[find(c)];
}
}
}
} int main()
{
int T;
scanf("%d",&T);
while (T--)
{
int m;
scanf("%d%d",&n,&m);
for (int i=;i<=n;i++)
{
mp[i].clear();
q[i].clear();
ans[i]=-;
f[i]=i;
vis[i]=;
}
for (int i=;i<n;i++)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
mp[a].push_back(node(b,c));
mp[b].push_back(node(a,c));
}
for (int i=;i<=m;i++)
{
int a,b;
scanf("%d%d",&a,&b);
q[a].push_back(node(b,i));
q[b].push_back(node(a,i));
}
vis[]=;
dis[]=;
lca(); for (int i=;i<=m;i++)
printf("%d\n",ans[i]);
}
return ;
}

是有问题的,但是数据弱所以没爆出来。

正确形式:

 #include<iostream>
#include<stdio.h>
#include<string.h>
#include<cmath>
#include<algorithm>
#include<string>
#include<vector>
using namespace std; #define N 51111
struct node
{
int v,w; node(int vv,int ww)
{
v=vv;
w=ww;
}
};
int f[N],dis[N],ans[N],vis[N],n;
vector<node>mp[N];
vector<node>q[N]; int find(int x)
{
if (f[x]!=x) f[x]=find(f[x]);
return f[x];
} void lca(int u)
{
for (int i=;i<mp[u].size();i++)
{
int v=mp[u][i].v;
if (vis[v]) continue;
vis[v]=; dis[v]=dis[u]+mp[u][i].w;
lca(v);
f[v]=u;
}
for (int j=;j<q[u].size();j++)
{
int c=q[u][j].v;
if (vis[c]&&ans[q[u][j].w]==-)
{
if (u==c) ans[q[u][j].w]=;
else ans[q[u][j].w]=dis[u]+dis[c]-*dis[find(c)];
}
} } int main()
{
int T;
scanf("%d",&T);
while (T--)
{
int m;
scanf("%d%d",&n,&m);
for (int i=;i<=n;i++)
{
mp[i].clear();
q[i].clear();
ans[i]=-;
f[i]=i;
vis[i]=;
}
for (int i=;i<n;i++)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
mp[a].push_back(node(b,c));
mp[b].push_back(node(a,c));
}
for (int i=;i<=m;i++)
{
int a,b;
scanf("%d%d",&a,&b);
q[a].push_back(node(b,i));
q[b].push_back(node(a,i));
}
vis[]=;
dis[]=;
lca(); for (int i=;i<=m;i++)
printf("%d\n",ans[i]);
}
return ;
}

可以仔细体验差别。

因为 在其中吃了大亏。HDU 2874 (都是简单题)卡了三天 。想想算法没错 ,果然是板子的问题。

换一种写法也可以,询问在递归前面也可以。

 #include<iostream>
#include<stdio.h>
#include<string.h>
#include<cmath>
#include<algorithm>
#include<string>
#include<vector>
using namespace std; #define N 21111
typedef long long ll;
struct node
{
int v,w;
node(int vv=,int ww=)
{
v=vv;
w=ww;
}
}; int f[N];
int ans[],dis[N];
int vis[N],mark[N]; vector<node>mp[N];
vector<node>q[N]; int find(int x)
{
if (f[x]!=x) f[x]=find(f[x]);
return f[x];
} void lca(int u)
{ for (int i=;i<q[u].size();i++)
{
int c=q[u][i].v;
int w=q[u][i].w;
if (vis[c]&&ans[w]==-&&mark[find(c)]!=)
{
ans[w]=dis[u]+dis[c]-*dis[find(c)];
}
} for (int i=;i<mp[u].size();i++)
{
int v=mp[u][i].v;
if (vis[v]) continue;
vis[v]=;
dis[v]=dis[u]+mp[u][i].w;
lca(v);
f[v]=u;
/*
for (int j=0;j<q[v].size();j++)
{
int c=q[v][j].v;
int w=q[v][j].w;
if (vis[c]&&ans[w]==-1&&mark[find(c)]!=1)
{
// if (v==c) ans[w]=0;
// else
ans[w]=dis[v]+dis[c]-2*dis[find(c)];
}
}
*/ }
} int main()
{
// freopen("input.txt","r",stdin);
// freopen("output1.txt","w",stdout);
int n,m,C;
while (scanf("%d%d%d",&n,&m,&C)!=EOF)
{
for (int i=;i<=n;i++)
{
f[i]=i;
mp[i].clear();
q[i].clear();
vis[i]=;
dis[i]=;
mark[i]=;
}
for (int i=;i<=C;i++) ans[i]=-;
for (int i=;i<=m;i++)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
mp[a].push_back(node(b,c));
mp[b].push_back(node(a,c));
}
for (int i=;i<=C;i++)
{
int a,b;
scanf("%d%d",&a,&b);
q[a].push_back(node(b,i));
q[b].push_back(node(a,i));
} for (int i=;i<=n;i++)
if (!vis[i])
{
vis[i]=;
dis[i]=;
lca(i);
mark[i]=;
} for (int i=;i<=n;i++)
for (int j=;j<q[i].size();j++)
{
int u=i;
int v=q[i][j].v;
int w=q[i][j].w;
if (find(u)!=find(v)) ans[w]=-;
} for (int i=;i<=C;i++)
if (ans[i]==-) printf("Not connected\n");
else printf("%d\n",ans[i]); }
return ;
}

LCA 笔记的更多相关文章

  1. 最近公共祖先算法LCA笔记(树上倍增法)

    Update: 2019.7.15更新 万分感谢[宁信]大佬,认认真真地审核了本文章,指出了超过五处错误捂脸,太尴尬了. 万分感谢[宁信]大佬,认认真真地审核了本文章,指出了超过五处错误捂脸,太尴尬了 ...

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

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

  3. 算法学习笔记:最近公共祖先(LCA问题)

    当我们处理树上点与点关系的问题时(例如,最简单的,树上两点的距离),常常需要获知树上两点的最近公共祖先(Lowest Common Ancestor,LCA).如下图所示: 2号点是7号点和9号点的最 ...

  4. 树的直径,LCA复习笔记

    前言 复习笔记第6篇. 求直径的两种方法 树形DP: dfs(y); ans=max( ans,d[x]+d[y]+w[i] ); d[x]=max( d[x],d[y]+w[i] ); int di ...

  5. 最近公共祖先(LCA)学习笔记 | P3379 【模板】最近公共祖先(LCA)题解

    研究了LCA,写篇笔记记录一下. 讲解使用例题 P3379 [模板]最近公共祖先(LCA). 什么是LCA 最近公共祖先简称 LCA(Lowest Common Ancestor).两个节点的最近公共 ...

  6. LCA学习笔记

    写在前面 目录 一.LCA的定义 二.暴力法求LCA 三.倍增法求LCA 四.树链剖分求LCA 五.LCA典型例题 题目完成度 一.LCA的定义 LCA指的是最近公共祖先.具体地,给定一棵有根树,若结 ...

  7. 关于LCA的倍增解法的笔记

    emmmmm近日刚刚学习了LCA的倍增做法,写一篇BLOG来加强一下印象w 首先 何为LCA? LCA“光辉”是印度斯坦航空公司(HAL)为满足印度空军需要研制的单座单发轻型全天候超音速战斗攻击机,主 ...

  8. LCA算法笔记

    LCA,最近公共祖先,实现有多种不同的方法,在树上的问题中有着广泛的应用,比如说树上的最短路之类. LCA的实现方法有很多,比如RMQ.树链剖分等. 今天来讲其中实现较为简单的三种算法: RMQ+时间 ...

  9. 倍增LCA学习笔记

    前言 ​ "倍增",作为一种二进制拆分思想,广泛用于各中算法,如\(ST\)表,求解\(LCA\)等等...今天,我们仅讨论用该思想来求解树上两个节点的\(LCA\)(最近公共祖先 ...

随机推荐

  1. 05-树9 Huffman Codes

    哈夫曼树 Yes 需满足两个条件:1.HuffmanTree 结构不同,但WPL一定.子串WPL需一致 2.判断是否为前缀码 开始判断用的strstr函数,但其传值应为char *,不能用在strin ...

  2. 第二十二章 数据访问(In .net4.5) 之 集合

    1. 概述 本章内容包括 .net平台中的集合.如何选择集合 以及 如何实现自定义集合. 2. 主要内容 2.1 使用数组(Array) ]; ; x < arrayOfInt.Length;  ...

  3. p ython笔记第一天

    一.Linux基础 - 计算机以及日后我们开发的程序防止的服务器的简单操作 二.Python开发 http://www.cnblogs.com/wupeiqi/articles/5433893.htm ...

  4. spring 基本操作总结主要是aop以及依赖注入的基本配置

    一所需架包 spring commom-logging.jar  spring.jar 注解 common-annotation.jar aop面向切面 aspectjrt.jar    aspect ...

  5. centos6.4 安装 hive 0.12.0

    环境:centos6.4  64bit, 前提:hadoop已经正常运行,可以使用hadoop dfsadmin -report查看 hive 解压   tar zcvf hive-0.12.0.ta ...

  6. (转)redis 学习笔记(1)-编译、启动、停止

    redis 学习笔记(1)-编译.启动.停止   一.下载.编译 redis是以源码方式发行的,先下载源码,然后在linux下编译 1.1 http://www.redis.io/download 先 ...

  7. 关于Objective-C格式化处理相关规范

    Objective-C格式字符串和C#有很大的差别,下面我们就来看看 在C#中我们可以这么做,简单例举几个: //格式化输出字符串 string word = "world"; s ...

  8. C# SQL增删查改

    DBHelper: /// <summary> /// 执行查询 /// </summary> /// <param name="sql">有效 ...

  9. 如何在Quartus II中设置Virtual pin

    为了验证FPGA工程中的某个模块的功能和时序的正确性,常常需要对其单独进行验证,但是这些模块通常都与内部的众多信号相连(如系统总线,中断信号线等),往往一个模块的对外接口引脚会多达几百个,对其单独仿真 ...

  10. 基于PBOC电子钱包的圈存过程详解

    基于pboc的电子钱包的圈存过程,供智能卡行业的开发人员参考 一. 圈存 首先终端和卡片有一个共同的密钥叫做圈存密钥:LoadKey   (Load即圈存的意思,unLoad,是圈提的意思) 假设Lo ...