Codeforces 832D
题目链接:http://codeforces.com/problemset/problem/832/D

题意:在一棵生成树上,给出了三个点,求三个点之间最大的相交点数。

分析:三个点没有规定起止点,所以求得就是其中两个点到第三个点的路径上的重复点数。(图有点丑 见谅)

也就相当于AB,BC,AC三条路径中的公共交点到ABC三点的最大边数。分别求出边数然后取最大值再+1就可以了,在得出具体的计算公式之后这应该算一道倍增/LCA模板题(划掉) 。

需要注意的是倍增求LCA需要bfs/dfs构造深度,再预处理祖先数组,这也是算法的核心,在这里维护一个数组DP[i][j],表示下标以i为起点的长度为2^j的序列的信息。倍增法中的DP[i][j]为:结点 i 的向上 2^j 层的祖先。其中,DP[i][0]为节点i的父节点。
递推方程: DP[i][j] = DP[ DP[i][j-1] ] [j-1]。
DP[i][j-1]是结点i往上跳2^(j-1) 层的祖先, DP[i][j-1] 上再向上跳2^ (j-1)层,相当于从结点i,先跳2^ (j-1)层,再跳2^ (j-1)层,最终到达2^j层。

void bfs() {queue<int> que;h[1] = 1;que.push(1);while (!que.empty()) {int u = que.front();que.pop();for (int i = head[u]; i != -1; i = e[i].next) {int v = e[i].v;if (h[v])continue;h[v] = h[u] + 1;//求结点所在的深度fa[v][0] = u;//给fa数组初始化每个结点的父节点que.push(v);}}
}
 for (j = 1; (1 << j) <= n; j++)for (i = 1; i <= n; i++)if (fa[i][j - 1])fa[i][j] = fa[fa[i][j - 1]][j - 1];//dp数组

LCA详解:

int lca(int u, int v) {if (h[u] < h[v])swap(u, v);//确保u的深度大于vfor (i = 20; i >= 0; i--)if (h[u] - (1 << i) >= h[v])u = fa[u][i];//往上跳,深度--,使两者先处于同一个深度if (u == v)return u;//如果已经处在同一个结点上直接returnfor (i = 20; i >= 0; i--) {//从大到小遍历回溯的高度,如果没有相遇就同时向上跳if (fa[u][i] != fa[v][i])u = fa[u][i], v = fa[v][i];}//最后一次会跳到以v,u的lca为父节点的两个节点上,返回此时u/v的父节点即可return fa[u][0];
}

计算(枚举)距离:

int dis(int u, int v) {return h[u] + h[v] - 2 * h[lca(u, v)];//相当于两个点的深度相加减去两倍的相交距离(lca到根节点的距离)
}

求(最大)重合距离:

int dis1 = dis(u, v), dis2 = dis(u, t), dis3 = dis(v, t);
int maxx = max((dis1 + dis2 - dis3) / 2, max((dis1 + dis3 - dis2) / 2, (dis2 + dis3 - dis1) / 2));

全部代码:

#include <algorithm> //swap
#include <iostream>
#include <cstring>
#include <map>
#include <queue>
using namespace std;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int maxn = 200010;
int i, j, k;
int m, n, q;
int head[maxn], h[maxn];
int fa[maxn][25];
int index;
struct node {int v, next;
} e[maxn];void add(int u, int v) {e[index].v = v;e[index].next = head[u];head[u] = index++;
}void bfs() {queue<int> que;h[1] = 1;que.push(1);while (!que.empty()) {int u = que.front();que.pop();for (int i = head[u]; i != -1; i = e[i].next) {int v = e[i].v;if (h[v])continue;h[v] = h[u] + 1;fa[v][0] = u;que.push(v);}}
}int lca(int u, int v) {if (h[u] < h[v])swap(u, v);for (i = 20; i >= 0; i--)if (h[u] - (1 << i) >= h[v])u = fa[u][i];if (u == v)return u;for (i = 20; i >= 0; i--) {if (fa[u][i] != fa[v][i])u = fa[u][i], v = fa[v][i];}return fa[u][0];
}int dis(int u, int v) {return h[u] + h[v] - 2 * h[lca(u, v)];
}int main() {while (cin >> n >> q) {int u, v, t;memset(head, -1, sizeof head);memset(h, 0, sizeof h);memset(fa, 0, sizeof fa);index = 0;for (i = 2; i <= n; i++) {cin >> u;add(u, i);add(i, u);}bfs();for (j = 1; (1 << j) <= n; j++)for (i = 1; i <= n; i++)if (fa[i][j - 1])fa[i][j] = fa[fa[i][j - 1]][j - 1];while (q--) {scanf("%d %d %d", &u, &v, &t);int dis1 = dis(u, v), dis2 = dis(u, t), dis3 = dis(v, t);int maxx = max((dis1 + dis2 - dis3) / 2, max((dis1 + dis3 - dis2) / 2, (dis2 + dis3 - dis1) / 2));cout << maxx + 1 << endl;}}return 0;
}

Codeforces 832D题解报告相关推荐

  1. 2015浙江财经大学ACM有奖周赛(一) 题解报告

    2015浙江财经大学ACM有奖周赛(一) 题解报告 命题:丽丽&&黑鸡 这是命题者原话. 题目涉及的知识面比较广泛,有深度优先搜索.广度优先搜索.数学题.几何题.贪心算法.枚举.二进制 ...

  2. CSP-2019day1题解报告

    day1题解报告 题目 T1 T2 从链想起 转为正解 T3(摘自同级大佬xez) 题目 T1传送门 T2传送门 T3传送门 T1 乍一看,这道题做过,可以用对称性做,如果他的长度过了一半,就输出1, ...

  3. 爆炸的符卡洋洋洒洒题解报告

    爆炸的符卡洋洋洒洒题解报告 标签:动态规划 题目链接 来源:牛客网 解题思路: 显而易见的背包问题 但再观察a,b的数据范围,开不了那么大的dp数组 这就启发我们去优化,由于题目要求魔力总耗的是k的倍 ...

  4. 2022杭电多校5题解报告(同步自语雀)

    一.赛后总结 Wuhu~萌新又来啦~ 第一次在考场上写出NTT,虽然是比较裸,但感觉真的不错~ 开场看03,思路比较直,就是dijk,但跨层跳跃想了好久~最后想到了类似于B树或者B-树一类的层内链表, ...

  5. 2022杭电多校4题解报告(同步自语雀)

    一.赛后总结 嘤嘤嘤,本人纯萌新,深夜反思自己到底有多菜~(:′⌒`) 前天没写出状压,再前面不会SAM和圆方树,再往前不会NTT和FFT,真的是个啥也不会的萌新呢. 这场主要的问题在于02的0环和1 ...

  6. 2022牛客多校2题解报告(同步自语雀)

    一.赛后总结 总结就是缺乏清晰的大脑,当然一切的一切归因于实力不足. 开局看K,半个小时推出DP式子,交了就WA.差错没查出来,写了暴力对拍,就去看D了.后来拍了3个小时也没出问题...可能是数据生成 ...

  7. 【题解报告】ZJNU综合训练(2021.1.26)

    [题解报告]ZJNU综合训练(2021.1.26) B C D F H I J M 综合训练 ZJNU综合训练(2021.1.26) B:DP+搜索 | CF 1057C C:组合数学+dp | CF ...

  8. 题解报告(CDUT暑期集训——第三场)

    题解报告(CDUT暑期集训--第三场) A - Problem A. Ascending Rating HDU - 6319 思路:单调队列板子题?(但是弱的一批的我还是不会用(有空补上 用的滑动窗口 ...

  9. 题解报告(CDUT暑期集训——第二场)

    题解报告(CDUT暑期集训--第二场) D - Game HDU - 6312 思路:水题 Alice一直是必胜态 AC代码 #include<stdio.h> #include<i ...

最新文章

  1. [改善Java代码]避开基本类型数组转换列表陷阱
  2. 深度卷积网络CNN与图像语义分割
  3. 【MySQL】mysql 远程连接111
  4. 《双人成行》如何炼就“教科书级别的合作体验游戏”典范?
  5. 服务器被一堆系统登录_WIN10做天高服务器客户端登录出现“操作系统原因无法登录”...
  6. 接收xml参数_SpringBoot实战(二):接收xml请求
  7. 程序出错后 程序员给测试人员的20条高频回复
  8. go语言net包rpc远程调用的使用
  9. 刷 携程 地面业务 前端面试经历
  10. java查询oracle数据库_Oracle数据库之java 从Oracle数据库到处数据到Elasticsearch全文检索库进行全文查询...
  11. matlab-lsqcurvefit函数
  12. Beyond Compare for MAC反编译class文件
  13. Linux 运行.exe程序
  14. 【idea】两台电脑协同办公
  15. Python学习笔记--Python 爬虫入门 -17-5 js 加密 (和有道词典的瓜葛)
  16. ERP的灵魂是管理思想
  17. Google Analytics Service account 认证指南
  18. LabVIEW图形化TensoRT工具包的安装下载分享
  19. IDEA下Git标签使用
  20. 经典坦克大战再现(一)

热门文章

  1. linux如何系统的学习?linux如何学习好?
  2. BUCK电路控制方式
  3. 多合一网站是共用服务器和域名吗,什么是五站合一、多站合一?
  4. Docker配置emqx环境(win11)
  5. 使用Debookee抓取同一网络中中任何设备的报文
  6. 字符串常量和字符串变量
  7. Android 不申请权限储存、删除相册图片
  8. [生化危机5]的图形渲染讲解
  9. ntp如何确认与服务器偏差_搭建NTP服务器
  10. 【getAttribute】【setAttribute】【removeAttribute】【attr】【remove】自定义属性的应用 怎么设置自定义属性 怎么修改删除自定义属性