/*********--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模板的更多相关文章

  1. 倍增求lca模板

    倍增求lca模板 https://www.luogu.org/problem/show?pid=3379 #include<cstdio> #include<iostream> ...

  2. HDU 2586——How far away ?——————【LCA模板题】

    How far away ? Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)To ...

  3. 算法复习——LCA模板(POJ1330)

    题目: Description A rooted tree is a well-known data structure in computer science and engineering. An ...

  4. 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 ...

  5. LCA模板(数剖实现)

    题目链接:https://www.luogu.org/problemnew/show/P3379 题意:LCA模板题. 思路:今天开始学树剖,先拿lca练练.树剖解lca,两次dfs复杂度均为O(n) ...

  6. POJ 1330 Nearest Common Ancestors(LCA模板)

    给定一棵树求任意两个节点的公共祖先 tarjan离线求LCA思想是,先把所有的查询保存起来,然后dfs一遍树的时候在判断.如果当前节点是要求的两个节点当中的一个,那么再判断另外一个是否已经访问过,如果 ...

  7. HDU2586 How far away ?(LCA模板题)

    题目链接:传送门 题意: 给定一棵树,求两个点之间的距离. 分析: LCA 的模板题目 ans = dis[u]+dis[v] - 2*dis[lca(u,v)]; 在线算法:详细解说 传送门 代码例 ...

  8. 最近公共祖先(LCA)模板

    以下转自:https://www.cnblogs.com/JVxie/p/4854719.html 首先是最近公共祖先的概念(什么是最近公共祖先?): 在一棵没有环的树上,每个节点肯定有其父亲节点和祖 ...

  9. HDU 2586 How far away ?(LCA模板 近期公共祖先啊)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2586 Problem Description There are n houses in the vi ...

随机推荐

  1. YTU 2990: 链表的基本运算(线性表)

    2990: 链表的基本运算(线性表) 时间限制: 1 Sec  内存限制: 128 MB 提交: 1  解决: 1 题目描述 编写一个程序,实现链表的各种基本运算(假设顺序表的元素类型为char),主 ...

  2. Javascript事件委托

      事件委托利用事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件未使用事件委托之前: <!DOCTYPE html> <html> <head> &l ...

  3. ROADS

    ROADS Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 11977 Accepted: 4429 Description N ...

  4. Tautology 分类: POJ 2015-06-28 18:40 10人阅读 评论(0) 收藏

    Tautology Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 10428   Accepted: 3959 Descri ...

  5. linux socket高性能服务器处理框架

    这个博客很多东西 http://blog.csdn.net/luozhonghua2014/article/details/37041765   思考一种高性能的服务器处理框架 1.首先需要一个内存池 ...

  6. 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 ...

  7. SharePoint自动化系列——创建MMS terms

    转载请注明出自天外归云的博客园:http://www.cnblogs.com/LanTianYou/ PowerShell脚本实现MMS group.termSet.terms的自动化创建: Add- ...

  8. C#中的字符串处理——找出最长数字子串

    百度测试部2015年10月份的面试题之——字符串处理,找出最长的子串. 代码如下: private static string SelectNumberFromString(string input) ...

  9. js调用MVC3自带js验证

    验证: if ($(this).is("form")) {                        return $(this).validate().checkForm() ...

  10. ViewState

    ViewState就像一个记录本,由于WebFormd的无状态性,刷新了页面.那么这个页面就和上一个页面没有任何关系了.为了使刷新前的页面和本页面产生联系,ViewState的作用就是记录刷新前页面的 ...