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 ...
随机推荐
- YTU 2990: 链表的基本运算(线性表)
2990: 链表的基本运算(线性表) 时间限制: 1 Sec 内存限制: 128 MB 提交: 1 解决: 1 题目描述 编写一个程序,实现链表的各种基本运算(假设顺序表的元素类型为char),主 ...
- Javascript事件委托
事件委托利用事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件未使用事件委托之前: <!DOCTYPE html> <html> <head> &l ...
- ROADS
ROADS Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 11977 Accepted: 4429 Description N ...
- Tautology 分类: POJ 2015-06-28 18:40 10人阅读 评论(0) 收藏
Tautology Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 10428 Accepted: 3959 Descri ...
- linux socket高性能服务器处理框架
这个博客很多东西 http://blog.csdn.net/luozhonghua2014/article/details/37041765 思考一种高性能的服务器处理框架 1.首先需要一个内存池 ...
- view class source code with JAD plugin in Eclipse
The default class viewer doesn't decompile the class file so you cannot open and check the source co ...
- SharePoint自动化系列——创建MMS terms
转载请注明出自天外归云的博客园:http://www.cnblogs.com/LanTianYou/ PowerShell脚本实现MMS group.termSet.terms的自动化创建: Add- ...
- C#中的字符串处理——找出最长数字子串
百度测试部2015年10月份的面试题之——字符串处理,找出最长的子串. 代码如下: private static string SelectNumberFromString(string input) ...
- js调用MVC3自带js验证
验证: if ($(this).is("form")) { return $(this).validate().checkForm() ...
- ViewState
ViewState就像一个记录本,由于WebFormd的无状态性,刷新了页面.那么这个页面就和上一个页面没有任何关系了.为了使刷新前的页面和本页面产生联系,ViewState的作用就是记录刷新前页面的 ...