hdu5156 LCA

2024-06-14 19:18
文章标签 lca hdu5156

本文主要是介绍hdu5156 LCA,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

具体解法就是bc首页的解法了,排个颜色序和dfs序,然后按照解法一路解下去就行了。注意一定要pai排dfs序,不然会更新错误的公共祖先节点。

代码:

#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
#include <stack>
#include <map>
#include <string>
#include <algorithm>
#define ll long long int
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define delf int m=(l+r)>>1using namespace std;int f[50005];       //当前集合的父节点为当前访问的子树公共祖先
int mark[50005];        
vector <int> m[50005];
vector <int> q[50005];
int ans[50005];
int id[50005];      //dfs序
int n,m1,cnt;struct color
{int v;int c;
} c[500005];bool cmp(color a,color b)
{if (a.c!=b.c)return a.c<b.c;return id[a.v]<id[b.v];
}void init()
{for (int i=1;i<=n;i++){m[i].clear();q[i].clear();}for (int i=1;i<=n;i++)ans[i]=0;for (int i=1;i<=n;i++)f[i]=i;for (int i=1;i<=n;i++)mark[i]=0;
}void dfs(int u,int t)
{id[u]=cnt++;for (int i=0;i<m[u].size();i++){if (m[u][i]==t)continue ;dfs(m[u][i],u);}
}int find(int x)
{if (f[x]==x)return x;return f[x]=find(f[x]);
}int LCA(int u,int t)
{for (int i=0;i<m[u].size();i++){if (m[u][i]==t)continue ;int s=LCA(m[u][i],u);ans[u]+=s;f[m[u][i]]=u;}for (int i=0;i<q[u].size();i++){if (mark[q[u][i]]==1)ans[find(q[u][i])]--;}mark[u]=1;return ans[u];
}int scan() {    //输入外挂int res = 0, flag = 0;char ch;if((ch = getchar()) == '-') flag = 1;else if(ch >= '0' && ch <= '9') res = ch - '0';while((ch = getchar()) >= '0' && ch <= '9')res = res * 10 + (ch - '0');return flag ? -res : res;
}void out(int a) {    //输出外挂if(a < 0) { putchar('-'); a = -a; }if(a >= 10) out(a / 10);putchar(a % 10 + '0');
}int main()
{while (~scanf("%d%d",&n,&m1)){init();for (int i=1;i<n;i++){int a,b;a=scan();b=scan();//scanf("%d%d",&a,&b);m[a].push_back(b);m[b].push_back(a);}for (int i=1;i<=m1;i++){int a,b;a=scan();b=scan();//scanf("%d%d",&a,&b);c[i].v=a;c[i].c=b;}cnt=1;dfs(1,0);       //获得每个节点dfs序位置sort(c+1,c+m1+1,cmp);       //按照颜色第一关键字,dfs序第二关键字排序,这样能保证颜色相同的节//点在访问时是顺序的,否则会因为减1的节点位置不对而出错。ans[c[1].v]++;for (int i=2;i<=m1;i++){if (c[i].c==c[i-1].c&&c[i].v==c[i-1].v)continue ;ans[c[i].v]++;if (c[i].c==c[i-1].c){q[c[i].v].push_back(c[i-1].v);q[c[i-1].v].push_back(c[i].v);}}int t=LCA(1,0);for (int i=1;i<n;i++){out(ans[i]);putchar(' ');}//printf("%d ",ans[i]);printf("%d\n",ans[n]);}
}


这篇关于hdu5156 LCA的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1061289

相关文章

poj1330(LCA最近公共祖先)

题意:求最近公共祖先 思路:之前学习了树链剖分,然后我就用树链剖分的一小部分知识就可以解这个题目了,记录每个结点的fa和depth。然后查找时,每次将depth大的结点往上走直到x = y。 代码如下: #include<iostream>#include<algorithm>#include<stdio.h>#include<math.h>#include<cstring>

【HDU】5574 Colorful Tree【子树染色,询问子树颜色数——线段树+bit+lca+set】

题目链接:【HDU】5574 Colorful Tree 题目大意:对一个子树染色,询问一个子树的颜色数。 题目分析: set set维护每种颜色所在的 dfs dfs序区间,修改均摊 nlogn nlogn。 #include <bits/stdc++.h>using namespace std ;typedef long long LL ;typedef pair < int , i

离线LCA学习

题目1 : 最近公共祖先·二 时间限制: 10000ms 单点时限: 1000ms 内存限制: 256MB 描述 上上回说到,小Hi和小Ho用非常拙劣——或者说粗糙的手段山寨出了一个神奇的网站,这个网站可以计算出某两个人的所有共同祖先中辈分最低的一个是谁。远在美国的他们利用了一些奇妙的技术获得了国内许多人的相关信息,并且搭建了一个小小的网站来应付来自四面八方的请

【LCA】vijos1427机密信息

描述 Lorabit有个很奇怪的习惯,他把他所有的机密信息都存放在一个叫机密盘的磁盘分区里,然而这个机密盘中却没有一个文件,那他是怎么存放信息呢?聪明的你一定想到了,Lorabit的信息都是以文件夹名称的形式保存的。Lorabit给机密盘中的每一个文件夹都编了号,而Lorabit的机密信息是由S文件夹转到T文件夹的过程中必须经过的文件夹名称组合而成的(包括S和T),由于Lorabit的磁盘很

【LCA】求最近公共祖先

算法一:在线算法 倍增 POJ1330 模板题 #include <stdio.h>#include <string.h>#include <iostream>#include <algorithm>#include <vector>#include <queue>#include <set>#include <map>#include <string>#include

poj 3694 Network(tarjan + LCA)

http://poj.org/problem?id=3694 题意:对于一个无向连通图,问加入某条边后,图中有桥的数目。 思路: 根据tarjan算法求出初始图的桥的数目,并用数组bridge标记桥的终点,在tarjan深搜树中求出每个节点的父节点(数组father表示)以及它们的深度,用于以后迭代求LCA。 因为加入某条边后,树中就会存在环,而环中的每条边都不再是桥,这就与求LCA

poj 1330 Nearest Common Ancestors(LCA模板)

http://poj.org/problem?id=1330 题意:给出两个点,求出这两个点最近的公共祖先。 求LCA的模板题。 大致思路就是访问到某个节点时,先将它自己加入集合中,然后递归访问它的子树,同时把子树加入到集合中来。子树搜索完毕后,判断该节点是否是输入的两个节点之一,若是,并且另外一个也已标记为访问过,那么另外一个节点的祖先便是他们的LCA。 #include<stdio

最近公共祖先(LCA),树上差分,树的直径总结

最近也是一不小心就学到了树论,这方面确实太不行了,也该开始学习一下了,那么话不多说,进入今日份的树论学习,直接开冲 最近公共祖先(LCA)——倍增思想(可以结合我之前写的ST表学习)   我们来看什么是最近公共祖先,对于9和8来讲,其最近公共祖先为6,对于3和7来讲,其最近公共祖先为5,那么我们去求最近公共祖先总共要有两步 第一步就是深搜,我们这一遍的深搜主要是为了去统计每一个点的深度

HDU 5150 UVALive 5061 (LCA标记)

这两题都是在树上求某一些路径上的点权的变化 两道题的思路相同 HDU 5150: 每一种颜色我们分开考虑他们对所有节点的贡献,对于颜色同为c的两个节点u和v(假设u!=v),那么在lca(u,v)的时候我们需要-1,因为在lca(u,v)一直到根的路径上,颜色c只能影响一次。基于此,我们对每种颜色的所有节点按照dfs序排好序,首先每个节点+1,然后对dfs序相邻的两个节点(注意颜色要相同)求

C++ P3379 【模板】最近公共祖先(LCA)

题目地址:https://www.luogu.org/problemnew/show/P3379 主要是用来作为参考代码的。 #include<cstdio>#include<iostream>using namespace std;int cnt=0,head[1000010],f[500010][21],d[1000010];struct Edge{int v,nxt;}e