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\)(最近公共祖先 ... 
随机推荐
- 05-树9 Huffman Codes
			哈夫曼树 Yes 需满足两个条件:1.HuffmanTree 结构不同,但WPL一定.子串WPL需一致 2.判断是否为前缀码 开始判断用的strstr函数,但其传值应为char *,不能用在strin ... 
- 第二十二章 数据访问(In .net4.5) 之 集合
			1. 概述 本章内容包括 .net平台中的集合.如何选择集合 以及 如何实现自定义集合. 2. 主要内容 2.1 使用数组(Array) ]; ; x < arrayOfInt.Length; ... 
- p ython笔记第一天
			一.Linux基础 - 计算机以及日后我们开发的程序防止的服务器的简单操作 二.Python开发 http://www.cnblogs.com/wupeiqi/articles/5433893.htm ... 
- spring 基本操作总结主要是aop以及依赖注入的基本配置
			一所需架包 spring commom-logging.jar spring.jar 注解 common-annotation.jar aop面向切面 aspectjrt.jar aspect ... 
- centos6.4 安装 hive 0.12.0
			环境:centos6.4 64bit, 前提:hadoop已经正常运行,可以使用hadoop dfsadmin -report查看 hive 解压 tar zcvf hive-0.12.0.ta ... 
- (转)redis 学习笔记(1)-编译、启动、停止
			redis 学习笔记(1)-编译.启动.停止 一.下载.编译 redis是以源码方式发行的,先下载源码,然后在linux下编译 1.1 http://www.redis.io/download 先 ... 
- 关于Objective-C格式化处理相关规范
			Objective-C格式字符串和C#有很大的差别,下面我们就来看看 在C#中我们可以这么做,简单例举几个: //格式化输出字符串 string word = "world"; s ... 
- C# SQL增删查改
			DBHelper: /// <summary> /// 执行查询 /// </summary> /// <param name="sql">有效 ... 
- 如何在Quartus II中设置Virtual pin
			为了验证FPGA工程中的某个模块的功能和时序的正确性,常常需要对其单独进行验证,但是这些模块通常都与内部的众多信号相连(如系统总线,中断信号线等),往往一个模块的对外接口引脚会多达几百个,对其单独仿真 ... 
- 基于PBOC电子钱包的圈存过程详解
			基于pboc的电子钱包的圈存过程,供智能卡行业的开发人员参考 一. 圈存 首先终端和卡片有一个共同的密钥叫做圈存密钥:LoadKey (Load即圈存的意思,unLoad,是圈提的意思) 假设Lo ... 
