LCA 笔记
简述这几天的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 笔记的更多相关文章
- 最近公共祖先算法LCA笔记(树上倍增法)
Update: 2019.7.15更新 万分感谢[宁信]大佬,认认真真地审核了本文章,指出了超过五处错误捂脸,太尴尬了. 万分感谢[宁信]大佬,认认真真地审核了本文章,指出了超过五处错误捂脸,太尴尬了 ...
- 算法笔记--lca倍增算法
算法笔记 模板: vector<int>g[N]; vector<int>edge[N]; ][N]; int deep[N]; int h[N]; void dfs(int ...
- 算法学习笔记:最近公共祖先(LCA问题)
当我们处理树上点与点关系的问题时(例如,最简单的,树上两点的距离),常常需要获知树上两点的最近公共祖先(Lowest Common Ancestor,LCA).如下图所示: 2号点是7号点和9号点的最 ...
- 树的直径,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 ...
- 最近公共祖先(LCA)学习笔记 | P3379 【模板】最近公共祖先(LCA)题解
研究了LCA,写篇笔记记录一下. 讲解使用例题 P3379 [模板]最近公共祖先(LCA). 什么是LCA 最近公共祖先简称 LCA(Lowest Common Ancestor).两个节点的最近公共 ...
- LCA学习笔记
写在前面 目录 一.LCA的定义 二.暴力法求LCA 三.倍增法求LCA 四.树链剖分求LCA 五.LCA典型例题 题目完成度 一.LCA的定义 LCA指的是最近公共祖先.具体地,给定一棵有根树,若结 ...
- 关于LCA的倍增解法的笔记
emmmmm近日刚刚学习了LCA的倍增做法,写一篇BLOG来加强一下印象w 首先 何为LCA? LCA“光辉”是印度斯坦航空公司(HAL)为满足印度空军需要研制的单座单发轻型全天候超音速战斗攻击机,主 ...
- LCA算法笔记
LCA,最近公共祖先,实现有多种不同的方法,在树上的问题中有着广泛的应用,比如说树上的最短路之类. LCA的实现方法有很多,比如RMQ.树链剖分等. 今天来讲其中实现较为简单的三种算法: RMQ+时间 ...
- 倍增LCA学习笔记
前言 "倍增",作为一种二进制拆分思想,广泛用于各中算法,如\(ST\)表,求解\(LCA\)等等...今天,我们仅讨论用该思想来求解树上两个节点的\(LCA\)(最近公共祖先 ...
随机推荐
- delphi常用函数过程
数据类型转化 1.1. 数值和字符串转化 Procedure Str(X [: Width [ : Decimals ]]; var S); 将数值X按照一定格式转化成字符串S.Wid ...
- Oracle 11g 执行计划管理1
1. 执行计划管理的工作原理 1.1控制执行计划的稳定性 11g之前,可以使用存储大纲(stored outline)和SQL Profile来固定某条SQL语句的执行计划,防止由于执行计划发生变化而 ...
- IOS下载资源zip到本地然后读取
思路是 1.ios下载服务器上的zip资源包(图片,声音等经过zip压缩的资源包)到本地 2.解压zip到程序目录 3.从程序目录加载资源文件 一.下载zip资源 [cpp]-(NSString*)D ...
- selenium+python登录登出百度,等待页面加载,鼠标定位
#coding:gbk from selenium import webdriver from selenium.webdriver.common.keys import Keys from sele ...
- 实战MySQL集群,试用CentOS 6下的MariaDB-Galera集成版
说起mysql的集群估计很多人会首先想起mysql自带的replication或者mysql-mmm.mysql-mmm其实也是基于mysql自带的replication的,不过封装的更好用一些,但是 ...
- 使用eclipse开发
Eclipse下载地址:http://www.eclipse.org/ 下载后进行解压缩,点击eclipse.exe即可使用eclipse workspace:工作区 Project:项目 ...
- java 命令对象简单学习实现:
命令模式:首先我们要知道命令模式的基本定义:来自客户端的请求传入一个对象,从而使你可用不同的请求对客户进行参数化.用于“行为请求者”与“行为实现者”解耦,可实现二者之间的松耦合,以便适应变化.分离变化 ...
- [Environment Build] Win10下Appach配置
1. Apache下载,登录http://httpd.apache.org/download.cgi,选择Files for Microsoft Windows, 有以下几个选择, 我选择的是Apac ...
- 九度oj 1528 最长回文子串
原题链接:http://ac.jobdu.com/problem.php?pid=1528 小白书上的做法,不过这个还要简单些... #include<algorithm> #includ ...
- Mac下如何显示隐藏文件/文件夹_百度经验
在应用程序里打开终端, cd 你的文件夹名 ls -a 即可显示该文件夹下的所有隐藏文件 如果你想打开整个系统的隐藏文件可以在终端下输入以下命令: defaults write com.apple ...