「LCA」[USACO10HOL]牛的政治Cow Politics

[USACO10HOL]牛的政治Cow Politics

题目链接:[USACO10HOL]牛的政治Cow Politics

题目大意

给你\(n\)个关系,再给你一共有多少个群落,每个关系包含两个内容,在哪个群落以及当前 \(i\) 节点的父亲节点是谁。然后让你求每个群落距离最远的两个点的距离是多大

题目题解

刚开始想的是树的直径,但看了下样例发现都是在一棵树上进行的,搜肯定不怎么好搜,想想其他的办法。然后又想到LCA可以求两点的距离,那么可以考虑用LCA求两点距离,这里我们通过题意理解可以知道,如果选择一个深度最深的点作为其中一个点,那么其定会有一种与其他点的距离方案是我们的答案(简单的贪心),那么我们先确定一点的位置,然后再通过遍历和计算直接计算最大的距离不就OK了吗,然后就... AC了

代码如下

//#define fre yes

#include <cstdio>
#include <cstring>
#include <iostream>

const int N = 200005;
int head[N << 1], to[N << 1], ver[N << 1];
int maxx[N], color[N], ans[N];
int depth[N], f[N][22], lg[N];

int n, m, root;

int tot;
void addedge(int x, int y) {
    ver[tot] = y;
    to[tot] = head[x];
    head[x] = tot++;
}

void dfs(int u, int fa) {
    depth[u] = depth[fa] + 1;
    f[u][0] = fa;
    for (int i = 1; (1 << i) <= depth[u]; i++) {
        f[u][i] = f[f[u][i - 1]][i - 1];
    }

    for (int i = head[u]; ~i; i = to[i]) {
        int v = ver[i];
        if(v != fa) {
            dfs(v, u);
        }
    }
}

int LCA(int u, int v) {
    if(depth[u] < depth[v]) {
        std::swap(u, v);
    }

    while(depth[u] > depth[v]) {
        u = f[u][lg[depth[u] - depth[v]] - 1];
    } if(u == v) return u;

    for (int i = lg[depth[u]] - 1; i >= 0; i--) {
        if(f[u][i] != f[v][i]) {
            u = f[u][i];
            v = f[v][i];
        }
    }

    return f[u][0];
}

int Dis(int u, int v) {
    return depth[u] + depth[v] - 2 * depth[LCA(u, v)];
}

int main() {
    memset(head, -1, sizeof(head));
    scanf("%d %d", &n, &m);
    for (int i = 1; i <= n; i++) {
        int x, u;
        scanf("%d %d", &x, &u);
        color[i] = x;
        addedge(i, u);
        addedge(u, i);
        if(!u) root = i;
    }

    dfs(root, -1);
    for (int i = 1; i <= n; i++) {
        lg[i] = lg[i - 1] + (1 << lg[i - 1] == i);
    }

    for (int i = 1; i <= n; i++) {
        if(depth[maxx[color[i]]] < depth[i]) {
            maxx[color[i]] = i;
        }
    }

    for (int i = 1; i <= n; i++) {
        ans[color[i]] = std::max(ans[color[i]], Dis(maxx[color[i]], i));
    }

    for (int i = 1; i <= m; i++) {
        printf("%d\n", ans[i]);
    }
}

原文地址:https://www.cnblogs.com/Nicoppa/p/11516131.html

时间: 2024-10-20 00:06:25

「LCA」[USACO10HOL]牛的政治Cow Politics的相关文章

「题解」:毛一琛/$cow$ $subsets$

问题 A: 毛一琛/$cow$ $subsets$ 时间限制: 1 Sec  内存限制: 512 MB 题面 题面谢绝公开. 题解 题名貌似是个大神??看起来像是签到题然后就死了. 首先$O(3^n)$算法显然.也显然过不去$20$的测试点. 正解是赫赫有名的$meet$ $in$ $the$ $middle$算法.数据在40以内的都能用$meet$ $in$ $the$ $middle$?? 对于两半路径,可以拼起来并且构成合法答案的条件是两人获得的分数相同. 所以一个比较聪明的办法是,不去记

「POJ3613」Cow Relays

「POJ3613」Cow Relays 传送门 就一个思想:\(N\) 遍 \(\text{Floyd}\) 求出经过 \(N\) 个点的最短路 看一眼数据范围,想到离散化+矩阵快速幂 代码: #include <cstring> #include <cstdio> #define rg register #define file(x) freopen(x".in", "r", stdin), freopen(x".out"

大数据和「数据挖掘」是何关系?---来自知乎

知乎用户,互联网 244 人赞同 在我读数据挖掘方向研究生的时候:如果要描述数据量非常大,我们用Massive Data(海量数据)如果要描述数据非常多样,我们用Heterogeneous Data(异构数据)如果要描述数据既多样,又量大,我们用Massive Heterogeneous Data(海量异构数据)--如果要申请基金忽悠一笔钱,我们用Big Data(大数据) 编辑于 2014-02-2817 条评论感谢 收藏没有帮助举报作者保留权利 刘知远,NLPer 4 人赞同 我觉得 大数据

从「集装箱」思考Docker风潮

从「集装箱」思考Docker风潮 -- Docker潮流下的赢家策略 By 高焕堂 (台灣Docker聯盟 主席) 2015/02/20 前言 在许多革命性转折里,经常出现集装箱的身影:它就像幸运草一般,总是带来许多幸福和财运.现在Docker风起云涌,再现集装箱身影,如果开放视野.大力支持它,持续发挥它的潜能和力量,则幸运草就会出现在我们身旁了. 由于Docker集装箱带来的商机,其最直接的受益者是软件管理者(或称维运者),例如软件测试工具业者.测试人员等.因此在今天,不论您是开发者或是维运者

AC日记——「SCOI2015」情报传递 LiBreOJ 2011

#2011. 「SCOI2015」情报传递 思路: 可持久化树状数组模板: 代码: #include <bits/stdc++.h> using namespace std; #define maxn 200005 #define maxm maxn*100 int deep[maxn],f[maxn],id[maxn],top[maxn],cnt,soot; int head[maxn],V[maxn],E[maxn],lar[maxn],size[maxn]; int val[maxm],

LibreOJ #2219. 「HEOI2014」大工程

二次联通门 : LibreOJ #2219. 「HEOI2014」大工程 /* LibreOJ #2219. 「HEOI2014」大工程 虚树 + dp 对于每次的关键点建好虚树后 考虑树形dp dp[i] 表示在以i为根的子树路径总长 size[i] 表示在以i为根的子树中关键点的个数 maxn为以i为根的子树中到关键点到根最长的路径长 ans1自己推一推就好 对于ans2 如果i是关键点,则直接用maxn[i]更新答案 否则用maxn[i]+maxn[child[i]]+dis(i,son[

程序员「奇葩」说

一直以来「奇葩」这个词都是偏贬义的,直到去年有个综艺节目叫「奇葩说」挺热闹,这里的人不一定是奇葩,更多指达人的意思. 「奇葩说」里的达人都是能说会道的,我的主业是程序员,所以只能写写在我职业生涯中碰到的一些「奇葩」程序员. 你懂的,我这里的「奇葩」没有任何贬义的意思. 月在胸襟人在途 我刚入行时的第一位项目经理,70后.那年三十出头,在银行客户现场做项目经理,负责一个二十来人的客户现场团队. 虽然他的职位是项目经理,但实际那时他真是一名地道的资深程序员. 70 后的程序员大都是从写 C 开始的,

—Libre#2009. 「SCOI2015」小凸玩密室

#2009. 「SCOI2015」小凸玩密室 内存限制:256 MiB时间限制:1000 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: 匿名 提交提交记录统计讨论测试数据 题目描述 小凸和小方相约玩密室逃脱,这个密室是一棵有 n nn 个节点的完全二叉树,每个节点有一个灯泡.点亮所有灯泡即可逃出密室.每个灯泡有个权值 Ai A_iA?i??,每条边也有个权值 bi b_ib?i??. 点亮第 1 11 个灯泡不需要花费,之后每点亮一个新的灯泡 V VV 的花费,等于上一个被点亮的

Loj #2553. 「CTSC2018」暴力写挂

Loj #2553. 「CTSC2018」暴力写挂 题目描述 temporaryDO 是一个很菜的 OIer .在 4 月,他在省队选拔赛的考场上见到了<林克卡特树>一题,其中 \(k = 0\) 的部分分是求树 \(T\) 上的最长链.可怜的 temporaryDO 并不会做这道题,他在考场上抓猫耳挠猫腮都想不出一点思路. 这时,善良的板板出现在了空中,他的身上发出璀璨却柔和的光芒,荡漾在考场上.''题目并不难.'' 板板说.那充满磁性的声音,让 temporaryDO 全身充满了力量. 他