Codeforces-832D-Misha, Grisha and Underground

来源:互联网 发布:淘宝网店怎么经营 编辑:程序博客网 时间:2024/06/03 20:58

题目链接

codeforces-832D

题目大意

给一个n个节点的树,然后q个询问,每一个询问给三个节点a,b,c
你可以选择其中一个节点,求另外两个点到这个点的 公共路径上的 最大点数?

数据范围

2n1e51q1e5

解题思路

可以将求点数转化为求边数,因为是树,所以点数就等于边数+1,而边数就是路径长度。
看到一个求公共路径长度的公式:
dist(x,y) 表示 x 节点 到 y 节点的长度。
若选择节点 a那么 c -> ab –>a 的公共路径长度为:
[dist(c,a)+dist(b,a)dist(b,c)]/2
这个画个图出来稍微想一想就知道了。选择 bc的以此类推。
至于求两点之间的距离,用LCA就可以了。
最后就只需要依次选择a,b,cMAX就好。

这道题刚好,复习了一下LCA,确实忘得差不多了。电脑里还没LCA的板子,一会儿过去写一份。

AC代码:

#include <cstdio>#include <cstring>#include <cstdlib>#include <cmath>#include <algorithm>using namespace std;typedef long long LL;const int MaxN = 1e5;int n, q, all;int pre[2 * MaxN + 5], last[MaxN + 5], other[2 * MaxN + 5];int dep[MaxN + 5];int up[MaxN + 5][22]; //up[i][j]表示i节点向上走2的j次方步所能到达的点void build(int x, int y){    pre[++all] = last[x];    last[x] = all;    other[all] = y;}void Dfs(int x, int fa){    dep[x] = dep[fa] + 1;    up[x][0] = fa;    for(int i = 1; i <= 20; i++)         up[x][i] = up[up[x][i - 1]][i - 1];//更新up    int ed = last[x], dr;    while(ed != -1) {        dr = other[ed];        if(dr != fa)            Dfs(dr, x);        ed = pre[ed];    }}int Get_LCA(int x, int y){    if(dep[x] < dep[y]) swap(x, y);    int d = dep[x] - dep[y];    for(int i = 0; i <= 20; i++) //是dep[x]和dep[y]的深度一样        if(d & (1 << i))            x = up[x][i];    if(x == y) return x;    for(int i = 20; i >= 0; i--) {        if(up[x][i] != up[y][i]) {            x = up[x][i];            y = up[y][i];        }    }    return up[x][0];    //为什么return这个?想一下就应该知道了}int get_dist(int x, int y){    int u = Get_LCA(x, y);    return dep[x] + dep[y] - 2 * dep[u];}int main(){    while(scanf("%d %d", &n, &q) != EOF)    {        all = -1;        memset(last, -1, sizeof(last));        for(int i = 2; i <= n; i++) {            int p;            scanf("%d", &p);            build(p, i); build(i, p);        }        dep[1] = 1;        Dfs(1, 0);        for(int i = 1; i <= q; i++) {            int a, b, c;            scanf("%d %d %d", &a, &b, &c);            int ans = 0;            int dis_ab = get_dist(a, b);            int dis_ac = get_dist(a, c);            int dis_bc = get_dist(b, c);            //画个图出来稍微观察一下就能得到这个公式            int na = (dis_ac + dis_ab - dis_bc) / 2;            int nb = (dis_ab + dis_bc - dis_ac) / 2;            int nc = (dis_ac + dis_bc - dis_ab) / 2;            ans = max(na + 1, max(nb + 1, nc + 1));            printf("%d\n", ans);        }        memset(pre, 0, sizeof(pre));        memset(other, 0, sizeof(other));        memset(dep, 0, sizeof(dep));        memset(up, 0, sizeof(up));    }    return 0;}
阅读全文
0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 淘宝盖楼上限了怎么办 交了学费做微淘客却加不到人怎么办 微淘客交首付不想做了怎么办 蚂蚁微客二维码推广怎么办 游拍主播申请手机号被注册怎么办 淘宝客不给力怎么办 淘宝买家确认收货超时怎么办 淘宝没收到货退款卖家不处理怎么办 微博红包都是字怎么办 500个访客没转化怎么办 店铺动态评分是0怎么办 京东店铺评分低怎么办 被淘宝主播屏蔽怎么办 在淘宝客推广后退款怎么办 生产出现异常时你应该怎么办 违规后的店铺没访客怎么办 淘宝少发货店家不承认怎么办 淘宝买东西店家不发货怎么办 淘宝店家拒绝同意退款怎么办 被淘宝店家骂了怎么办 淘宝买家骂店家骚扰店家怎么办? 不想开淘宝店了怎么办 我是客服经常有客户骂人怎么办 淘宝直播前期没人看怎么办 淘宝被投诉商标侵权怎么办 淘宝后商家页面打不开了怎么办 淘宝遇到职业打假人怎么办 发票被复写上字怎么办 淘宝直播广告图片的商品怎么办 美团商家排名低怎么办 想成为淘宝主播怎么办 用移动流量很卡怎么办 淘宝店铺被恶意刷流量怎么办 一个想要公司权利的人怎么办 淘宝商家短信推广告怎么办 在群里乱发信息怎么办 支付宝扫不了码怎么办 淘宝商家收款不发货怎么办 淘宝申请退款商家拒绝怎么办 一件代发找不到供货商怎么办 淘宝京东兼职上当怎么办