CodeForces
来源:互联网 发布:ui设计师软件 编辑:程序博客网 时间:2024/06/14 06:43
题目链接:http://codeforces.com/problemset/problem/832/D
题目大意:一棵树上取3个点,求其它两点到一个点的点的最大重合数
解题思路:求出重合边数,重合点数就等于重合边数+1,假设是点a和点b到点c,那么重合边数=(dis(a,c)+dis(b,c)-dis(a,b))/2,因为要不断访问两个点的距离,所以考虑用Lca,先求出公共祖先,假设lca(a,b)=r,那么dis(a,b)=dep(a)-dep(r)+dep(b)-dep(r),即dep(a)+dep(b)-2*dep(r)
小结:Lca可用于树上快速求两点距离
AC代码:
#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int MAXN = 100000 + 5;struct Edge{ int v, next; Edge(int v = 0, int next = 0) :v(v), next(next) {}}edge[MAXN << 1];int head[MAXN], edgenum;int dep[MAXN << 1], tot, first[MAXN], tag[MAXN << 1];int st[MAXN << 1][30];int ans;void toInit(){ tot = 0; memset(head, -1, sizeof(head)); edgenum = 0;}void toAdd(int u, int v){ edge[edgenum] = Edge(v, head[u]); head[u] = edgenum++;}void toDfs(int u, int fa, int tier){ dep[++tot] = tier; tag[tot] = u; first[u] = tot; for (int i = head[u];i != -1;i = edge[i].next) { int v = edge[i].v; if (v == fa) continue; toDfs(v, u, tier + 1); dep[++tot] = tier; tag[tot] = u; }}void getSt(int n){ for (int i = 1;i <= n;++i) st[i][0] = i; for (int j = 1;1 << j <= n;++j) for (int i = 1;i + (1 << j) - 1 <= n;++i) { int st1 = st[i][j - 1], st2 = st[i + (1 << j - 1)][j - 1]; st[i][j] = dep[st1] < dep[st2] ? st1 : st2;//保存最小深度的所在数组中的位置 }}int toRmq(int l, int r){ int k = 0; while (1 << k <= r - l + 1) k++; k--; int st1 = st[l][k], st2 = st[r + 1 - (1 << k)][k]; return dep[st1] < dep[st2] ? st1 : st2;}int toLca(int x, int y){ x = first[x], y = first[y]; if (x > y) swap(x, y);//用于Rmq左右端点,所以要交换大小 return tag[toRmq(x, y)];//返回节点编号}int getDis(int x, int y){//因为r,x,y都是节点编号,先用first找到他们所在数组中的位置 int r = toLca(x, y); return dep[first[x]] + dep[first[y]] - 2 * dep[first[r]];}void toSolve(int a, int b, int c){ int tmp = getDis(a, b) + getDis(a, c) - getDis(b, c); ans = max(ans, tmp / 2);}int main(){ int n, q; scanf("%d%d", &n, &q); toInit(); for (int i = 2;i <= n;++i) { int pi;scanf("%d", &pi); toAdd(i, pi); toAdd(pi, i); } toDfs(1, 1, 0); getSt(tot);//tot=2*n-1; while (q--) { int a, b, c; ans = 0; scanf("%d%d%d", &a, &b, &c); toSolve(a, b, c); toSolve(b, a, c); toSolve(c, a, b); printf("%d\n", ans + 1); } return 0;}
阅读全文
0 0
- codeforces~~~
- Codeforces
- codeforces
- Codeforces
- codeforces
- codeforces
- Codeforces
- Codeforces
- CodeForces
- CodeForces
- CodeForces
- CodeForces
- CodeForces
- Codeforces
- Codeforces
- Codeforces
- Codeforces
- Codeforces
- 图的深度优先搜索算法DFS
- use32.dll接口函数
- 鼠标点击的涟漪效果(unity&shader)
- Redis高可用简易搭建
- 线段树区间更新模板 POJ
- CodeForces
- rsync与sersync的安装
- HDUOJ 1875 畅通工程再续 (kruskal算法)
- hdu 6112 今夕何夕
- linux查看终端进程占用资源
- 动态规划之背包问题0.1
- FW(固件)库函数RCC_GetClocksFreq()
- vs2015字符格式转换代码
- 数据库优化手段