LCA模板
/*********--LCA模板--***************/
//设置好静态参数并构建好图的邻接表,然后调用lca_setquery()设置查询
//最后调用lca_start(),在lca::dfs中的your code处理每次查询
//复杂度O(M+Q)
//表示图的邻接表 #define N 40100
#define MAX_Q 200 struct node
{
int to,next,w;
}edge[*N]; int pre[N],cnt; int ans[MAX_Q]; void add_edge(int u,int v,int w)
{
edge[cnt].w = w;
edge[cnt].to = v;
edge[cnt].next =pre[u];
pre[u] = cnt++;
} struct LCA
{
int ln;//表示图中的点,默认范围为[1,n]
int bin[N],bw[N]; // 并查集 与 bw记录到根节点的深度
struct node1
{
int to,next;
int id;
}edge1[MAX_Q*];
int pre1[N],cnt1;
int lmark[N]; void init(int n)//初始化传入点的个数n
{
ln = n;
cnt1 = ;
memset(pre1,-,sizeof(pre1));
memset(lmark,,sizeof(lmark));
for(int i=;i<=n;i++)
bin[i] = i;
} void add_edge1(int u,int v,int id)
{
edge1[cnt1].id = id;//查询的id
edge1[cnt1].to = v;
edge1[cnt1].next = pre1[u];
pre1[u]=cnt1++;
} int find(int v)
{
if(bin[v]==v) return v;
return bin[v]=find(bin[v]);
} void lca_setquery(int m)
{
//把所有的查询加入
//add_edge1(a,b);
//add_edge1(b,a);
for(int i=;i<m;i++)
{
int a,b;
scanf("%d%d",&a,&b);
add_edge1(a,b,i);
add_edge1(b,a,i);
}
} void dfs(int s,int w,int fa)
{
bw[s]=w;
for(int p=pre[s];p!=-;p=edge[p].next)
{
int v=edge[p].to;
if(v == fa) continue;//不到父亲节点
if(lmark[v]==)
{
//dfs(v,w+1,s);
dfs(v,w+edge[p].w,s);
bin[v]=s;
}
}
lmark[s] = ;
//遍历需要查询的点对
for(int p=pre1[s];p!=-;p=edge1[p].next)
{
int v = edge1[p].to;
if(lmark[v] == )//这个点已经处理过了
{
int x = find(v); //最近公共祖先
int dis = bw[v]-bw[x]+bw[s]-bw[x];//两点之间在树上最近距离(这里默认树边为1)
// your code
//ans[ edge1[p].id ] = dis;
//
}
} } void lca_start()
{
dfs(,,-);//第一个参数表示根节点
} }lca; //给出大小为n的树,查询m次两点最短距离
//int main()
//{
// int T;
// cin>>T;
// while(T--)
// {
// int n,m;
// scanf("%d%d",&n,&m);
// cnt = 0;
// memset(pre,-1,sizeof(pre));
// for(int i=1;i<n;i++)
// {
// int a,b,c;
// scanf("%d%d%d",&a,&b,&c);
// add_edge(a,b,c);
// add_edge(b,a,c);
// }
//
// lca.init(n);
// lca.lca_setquery(m);
// lca.lca_start();
// for(int i=0;i<m;i++) printf("%d\n",ans[i]);
// }
// return 0;
//}
2.LCA 在线建立rmq(nlog(n)) 查询(log(n))
#define N 40040
#define LN 20
struct node
{
int to,next;
}edge[*N]; int cnt,pre[N]; void add_edge(int u,int v)
{
edge[cnt].to = v;
edge[cnt].next = pre[u];
pre[u] = cnt++;
} struct Lca_Online
{
int _n;
int deep[N];
int dp[N][LN];
void _dfs(int s,int fa,int dd)
{
deep[s] = dd;
for(int p=pre[s];p!=-;p=edge[p].next)
{
int v = edge[p].to;
if(v == fa) continue;
_dfs(v,s,dd+);
dp[v][] = s;
}
} void _init()
{
for(int j=;(<<j)<=_n;j++)
{
for(int i=;i<=_n;i++)
{
if(dp[i][j-]!=-) dp[i][j] = dp[ dp[i][j-] ][j-];
}
}
}
void lca_init(int n)
{
_n = n;
memset(dp,-,sizeof(dp));
//_dfs(firstid,-1,0);
_dfs(,-,);
_init();
} int lca_query(int a,int b)
{
if(deep[a]>deep[b]) swap(a,b);
//调整b到a的同一高度
for(int i=LN-;deep[b]>deep[a];i--)
if(deep[b]-(<<i) >= deep[a]) b = dp[b][i];
if(a == b) return a;
for(int i=LN-;i>=;i--)
{
if(dp[a][i]!=dp[b][i]) a = dp[a][i],b = dp[b][i];
}
return dp[a][];
}
}lca; //int d[N];
//int main(int argc, const char * argv[]) {
// int T;
// cin>>T;
// while(T--)
// {
// memset(d,0,sizeof(d));
// cnt = 0;
// memset(pre,-1,sizeof(pre));
// int n;
// scanf("%d",&n);
// for(int i=1;i<n;i++)
// {
// int a,b;
// scanf("%d%d",&a,&b);
// add_edge(a, b);
// add_edge(b, a);
// d[b]++;
// }
// for(int i=1;i<=n;i++)
// {
// if(d[i] == 0) firstid = i;
// }
// int a,b;
// cin>>a>>b;
// lca.lca_init(n);
// printf("%d\n",lca.lca_query(a, b));
// }
// return 0;
//}
LCA模板的更多相关文章
- 倍增求lca模板
倍增求lca模板 https://www.luogu.org/problem/show?pid=3379 #include<cstdio> #include<iostream> ...
- HDU 2586——How far away ?——————【LCA模板题】
How far away ? Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)To ...
- 算法复习——LCA模板(POJ1330)
题目: Description A rooted tree is a well-known data structure in computer science and engineering. An ...
- hdu 2586 How far away?(LCA模板题+离线tarjan算法)
How far away ? Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)To ...
- LCA模板(数剖实现)
题目链接:https://www.luogu.org/problemnew/show/P3379 题意:LCA模板题. 思路:今天开始学树剖,先拿lca练练.树剖解lca,两次dfs复杂度均为O(n) ...
- POJ 1330 Nearest Common Ancestors(LCA模板)
给定一棵树求任意两个节点的公共祖先 tarjan离线求LCA思想是,先把所有的查询保存起来,然后dfs一遍树的时候在判断.如果当前节点是要求的两个节点当中的一个,那么再判断另外一个是否已经访问过,如果 ...
- HDU2586 How far away ?(LCA模板题)
题目链接:传送门 题意: 给定一棵树,求两个点之间的距离. 分析: LCA 的模板题目 ans = dis[u]+dis[v] - 2*dis[lca(u,v)]; 在线算法:详细解说 传送门 代码例 ...
- 最近公共祖先(LCA)模板
以下转自:https://www.cnblogs.com/JVxie/p/4854719.html 首先是最近公共祖先的概念(什么是最近公共祖先?): 在一棵没有环的树上,每个节点肯定有其父亲节点和祖 ...
- HDU 2586 How far away ?(LCA模板 近期公共祖先啊)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2586 Problem Description There are n houses in the vi ...
随机推荐
- API判断网站IP地址,国家区域
直接访问http://api.wipmania.com/jsonp 还有经纬度
- Google Analytics Premium VS Adobe Analytics
在很久以前的互联网年代,Google收购了一家名为Urchin的公司,进而演化诞生了Google Analytics.当Goochin(Google / Urchin)首次亮相时,它被所有人称为“新的 ...
- Ubiquitous Religions 分类: POJ 2015-06-16 17:13 11人阅读 评论(0) 收藏
Ubiquitous Religions Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 26678 Accepted: ...
- C#中进行单元测试
首先创建一个项目,写一段待测的程序: namespace ForTest { public class Program { static void Main(string[] args) { } pu ...
- git总结
1.先画个图,先对git的操作有个直观了解 2.分析下git中文件是怎么存储的 正如下面所示git存储不是每次更改就会产生一个新的文件,而是产生一个版本,这个版本对应着记录每个文件的不同情况 具体的存 ...
- 多条件查询(php+mysql) 租房子例子
<body> <?php //多条件 $tiaojian2= " 2=2 "; $attr2 = ""; //判断区域 if(!empty($ ...
- File.separator
摘自:http://blog.csdn.net/chindroid/article/details/7735832
- shell 随机从文件中抽取若干行
shuf -n5 main.txt sort -R main.txt | head -5 awk -vN=5 -vC="`wc -l file`" 'BEGIN{srand();w ...
- Django基础-过滤器
1.可以通过过滤器来修改变量的显示,过滤器的形式是:{{ variable | filter }},管道符号'|'代表使用过滤器 2.过滤器能够采用链式的方式使用,例如:{{ text | escap ...
- VBA中方法的函数式调用和过程式调用的差别
因见到有人求助批量设置工作簿中的超链接,尝试写了一段代码: Sub AddHyperlinks() Dim strName As String, source As String, target As ...