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\)(最近公共祖先 ...
随机推荐
- QQ消息99+形成--第三方开源--BezierView
Android第三方开源的BezierView实现了上述QQ的99+条未读消息气泡显示.Android开源BezierView在github上的项目主页是:https://github.com/che ...
- JSON (仅限本地)
<script type="text/javascript"> setInterval(function() { $("#content").loa ...
- Keil的使用方法 - 常用功能(一)
Ⅰ.概述 学习一门软件的开发,开发工具的掌握可以说尤为重要.由于Keil集成开发工具支持多种MCU平台的开发,是市面上比较常见的,也是功能比较强大一款IDE.所以,对于大多数人说,选择Keil几乎是单 ...
- char const*, char*const, const char *const的区别
C++标准规定,const关键字放在类型或变量名之前等价的.所以,const char*和 char const*是一样的. const char* //常量指针---指向常量的指针----指针指 ...
- (1)c语言学习总结之从关键字到循环结构
一.关键字和标示符 1.关键字:c规定的有特殊含义的单词(也就是系统起的名字),全部是小写,有32个; 由关键字引出数据类型和流程类型 1.分类: (1)数据类型:整型用int标示,字符型用char表 ...
- EMVTag系列3《持卡人基本信息数据》
Ø 9F61 持卡人证件号 L:2–26 R(需求):数据应存在,在读应用数据过程中,终端不检查: (PBOC2.0第五部分中规定)芯片中持卡人姓名 5F20与持卡人姓名扩展9F0B只能使用一 ...
- poj 2485 Highways
题目连接 http://poj.org/problem?id=2485 Highways Description The island nation of Flatopia is perfectly ...
- hdu 1434 幸福列车
题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=1434 幸福列车 Description 一批幸福的列车即将从杭州驶向幸福的终点站——温州,身为总列车长 ...
- SQL Server实现数据的递归查询
在一次项目中遇到一种需求,需要记录某产品的替换记录. 实际应用举例为:产品101被201替换,之后201又被303替换,303又被109替换:产品102被202替换,之后202又被105替换. 现在我 ...
- OpenStack的bridge_sto off的解释
北京_张华(28620211) 2014/1/27 星期一 11:10:57传统的网络是通过STP协议来避免交换机在二层形成环路,但是对于虚拟交换机,因为有东西向的流量,故将bridge_stp设成o ...