简述这几天的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. CodeBlocks集成cppcheck

    From:http://www.cnblogs.com/killerlegend/p/3624117.html Writer:KillerLegend CodeBlocks本身配置了cppcheck的 ...

  2. Laravel 5 基础(十一)- 表单验证

    在建立一个文章的时候,如果你什么都不输入直接提交,ok,你获得了一个空的文章,没有任何错误提示,这是不对的.在命令行下运行 php artisan 可以看到一个选项 make:request,新建一个 ...

  3. LC.exe exited with code -1

    昨天从win8.1升级到win10之后, 一切还算顺利, 就是升级时间比较长. 但是快下班的时候 遇到一个问题, 是之前在win8.1上没遇到的, 首先代码win8.1 vs2013 上跑的时候一切正 ...

  4. 浅谈HAL

    参考:http://blog.csdn.net/mr_raptor/article/details/8074549 代码实现:http://blog.csdn.net/mr_raptor/articl ...

  5. hdu 3530 Subsequence

    题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=3530 Subsequence Description There is a sequence of i ...

  6. 使用IC框架开发跨平台App的备忘录123

    1,关于图标与启动屏幕 icon.png 192x192splash.png 2208x2208 将这两个图片放在resources目录下,在终端执行:ionic resources --iocn - ...

  7. Nginx Gzip 压缩配置

    Nginx Gzip 压缩配置 随着nginx的发展,越来越多的网站使用nginx,因此nginx的优化变得越来越重要,今天我们来看看nginx的gzip压缩到底是怎么压缩的呢? gzip(GNU-Z ...

  8. IOS之UIView的tag学习

    tag是UIView的一个属性,而且要求tag值唯一.父视图可以通过tag来找到一个子视图 UIView *redView = [[UIView alloc]initWithFrame:CGRectM ...

  9. js selector libray

    http://sizzlejs.com/ http://selectivizr.com/

  10. PHP URL 重定向 的三种方法(转载)

    为了方便查询,转载一篇. 1.使用header()函数    PHP的HTTP相关函数种提供了一个 header()函数,首先要清楚,header()函数必须放在php程序的开头部分,而且之前不能有另 ...