简述这几天的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. android AES 部分机器javax.crypto.BadPaddingException: pad block corrupted

    package com.bbguoxue.poetry.util; import java.security.SecureRandom; import javax.crypto.Cipher; imp ...

  2. setTimeOut(),和setInterVal()调用函数加不加括号!!!

    直接在ready中调用其他方法,会提示缺少对象的错误,解决方法如下: 方法1. 应用jQuery的扩展可以解决这个问题. $(document).ready(function(){ $.extend( ...

  3. [div+css布局]命名规则

    //首页可能碰到的 页头:header登录条:loginBar标志:logo侧栏:sideBar广告:banner导航:nav子导航:subNav菜单:menu子菜单:subMenu搜索:search ...

  4. 【转】C#中Invoke的用法

    在多线程编程中,我们经常要在工作线程中去更新界面显示,而在多线程中直接调用界面控件的方法是错误的做法,Invoke 和 BeginInvoke 就是为了解决这个问题而出现的,使你在多线程中安全的更新界 ...

  5. bhrs报表年结步骤

    --前期准备数据三个表数据: s_subjtotal_year, subject_item, branch ,decrsubjtotal---informix 查看数据库剩余空间select d.na ...

  6. Java通过SpyMemcached来缓存数据

    配置好Magent+memcached后,很明显数据之间的输入与输出都是通过代理服务器的,magent是做代理服务器的很明显java在memecached的调用驱动在magent同样适用. 这里选择S ...

  7. SaaS应用“正益工作”发布,为大中型企业轻松构建移动门户

    6月24日,以“平台之上,应用无限”为主题的2016 AppCan移动开发者大会,在北京国际会议中心隆重举行,逾1500名移动开发者一起见证了此次大会盛况. 会上,在专家领导.技术大咖.移动开发者的共 ...

  8. [转]NHibernate之映射文件配置说明

    1. hibernate-mapping 这个元素包括以下可选的属性.schema属性,指明了这个映射所引用的表所在的schema名称.假若指定了这个属性, 表名会加上所指定的schema的名字扩展为 ...

  9. homework-05 大家一起玩游戏~

    046  195 1.接口设计 客户端 用户登录后,启动一个线程来进行游戏,等待服务器信息及发送新数据 服务器  开始时,主程序一直等待用户登录,有新用户登录就开一个线程去为其服务 等到用户都登录完成 ...

  10. 与电子钱包相关的APDU指令

    CLS:命令报文的类别字节,class byte(类别字节) of command message(命令报文) UranusPay ED/EP: UranusPay是HB公司开发的COS,而ED是电子 ...