原题链接

题意

  • 给我们一棵n+1节点,n条边的树,然后给我们p条路径(每条路径给出两个端点)。我们需要从树上选出一些点,使得每条路径都至少包含我们选出的一个点。求最少选多少点。

思路

  • 以1为根,我们可以发现如果两条路径相交,设两条路径两端点的LCA分别是u,v,其中u的深度大于等于v的深度,则交点一定包含u。
  • 所以我们按照LCA的深度对读入的路径进行排序,然后按照深度从大到小进行遍历,如果发现当前路径的两端点属于之前已经标记过的子树,则此路径不需要选点,否则选择本条路径两端点的LCA,同时将该点所代表的子树进行标记,可以使用树链剖分和树状数组来完成这一任务。

AC代码

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define lowbit(x) (x&(-x)) using namespace std; const int N = 10000; int n;
int fir[N + 5], nex[N * 2 + 5], vv[N * 2 + 5], co = 0; void adde(int u, int v)
{
vv[++co] = v;
nex[co] = fir[u];
fir[u] = co;
} int fa[N + 5];
int sq[N + 5], rk[N + 5], dep[N + 5];
int st[N + 5], sz[N + 5], chi[N + 5]; int cc[N + 5]; void update(int x, int v)
{
while (x <= n + 1)
{
cc[x] += v;
x += lowbit(x);
}
} int qu(int x)
{
int res = 0;
while (x)
{
res += cc[x];
x -= lowbit(x);
}
return res;
} struct ab
{
int f;
int u;
int v;
bool operator < (const ab& c) const
{
return dep[f] > dep[c.f];
}
} qq[N * 5 + 5]; void dfs1(int o, int f)
{
fa[o] = f;
dep[o] = dep[f] + 1;
sz[o] = 1;
chi[o] = 0;
for (int i = fir[o]; i; i = nex[i])
{
if (vv[i] == f)
{
continue;
}
dfs1(vv[i], o);
sz[o] += sz[vv[i]];
if (sz[vv[i]] > sz[chi[o]])
{
chi[o] = vv[i];
}
}
} void dfs2(int o, int f, int top)
{
sq[++co] = o;
rk[o] = co;
st[o] = top;
if (chi[o])
{
dfs2(chi[o], o, top);
}
for (int i = fir[o]; i; i = nex[i])
{
if (vv[i] == f || vv[i] == chi[o])
{
continue;
}
dfs2(vv[i], o, vv[i]);
}
} int lca(int u, int v)
{
while (st[u] != st[v])
{
if (dep[st[u]] < dep[st[v]])
{
swap(u, v);
}
u = fa[st[u]];
}
return dep[u] < dep[v] ? u : v;
} int main()
{
while (scanf("%d", &n) == 1)
{
memset(fir, 0, sizeof(int) * (n + 2));
memset(cc, 0, sizeof(int) * (n + 2));
co = 0;
for (int i = 1; i <= n; ++i)
{
int u, v;
scanf("%d%d", &u, &v);
++u;
++v;
adde(u, v);
adde(v, u);
}
co = 0;
dfs1(1, 0);
dfs2(1, 0, 1);
int q;
scanf("%d", &q);
for (int i = 1; i <= q; ++i)
{
int u, v;
scanf("%d%d", &u, &v);
++u;
++v;
qq[i] = {lca(u, v), u, v};
}
sort(qq + 1, qq + q + 1);
int ans = 0;
for (int i = 1; i <= q; ++i)
{
if (qu(rk[qq[i].u]) || qu(rk[qq[i].v]))
{
continue;
}
++ans;
update(rk[qq[i].f], 1);
update(rk[qq[i].f] + sz[qq[i].f], -1);
}
printf("%d\n", ans);
}
return 0;
}

HDU 6203 ping ping ping 最近公共祖先 树状数组的更多相关文章

  1. 51nod 1681 公共祖先 | 树状数组

    51nod 1681 公共祖先 有一个庞大的家族,共n人.已知这n个人的祖辈关系正好形成树形结构(即父亲向儿子连边). 在另一个未知的平行宇宙,这n人的祖辈关系仍然是树形结构,但他们相互之间的关系却完 ...

  2. hdu 1556:Color the ball(第二类树状数组 —— 区间更新,点求和)

    Color the ball Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)To ...

  3. HDU 3887:Counting Offspring(DFS序+树状数组)

    http://acm.hdu.edu.cn/showproblem.php?pid=3887 题意:给出一个有根树,问对于每一个节点它的子树中有多少个节点的值是小于它的. 思路:这题和那道苹果树是一样 ...

  4. HDU 5654 xiaoxin and his watermelon candy 离线树状数组 区间不同数的个数

    xiaoxin and his watermelon candy 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5654 Description Du ...

  5. HDU 5293 Annoying problem 树形dp dfs序 树状数组 lca

    Annoying problem 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5293 Description Coco has a tree, w ...

  6. HDU 5877 2016大连网络赛 Weak Pair(树状数组,线段树,动态开点,启发式合并,可持久化线段树)

    Weak Pair Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others) Tota ...

  7. HDU 2227 Find the nondecreasing subsequences dp思想 + 树状数组

    http://acm.hdu.edu.cn/showproblem.php?pid=2227 用dp[i]表示以第i个数为结尾的nondecreasing串有多少个. 那么对于每个a[i] 要去找 & ...

  8. POJ 3321:Apple Tree + HDU 3887:Counting Offspring(DFS序+树状数组)

    http://poj.org/problem?id=3321 http://acm.hdu.edu.cn/showproblem.php?pid=3887 POJ 3321: 题意:给出一棵根节点为1 ...

  9. hdu 4715 Difference Between Primes(素数筛选+树状数组哈希剪枝)

    http://acm.hdu.edu.cn/showproblem.php?pid=4715 [code]: #include <iostream> #include <cstdio ...

  10. HDU 4605 Magic Ball Game (dfs+离线树状数组)

    题意:给你一颗有根树,它的孩子要么只有两个,要么没有,且每个点都有一个权值w. 接着给你一个权值为x的球,它从更节点开始向下掉,有三种情况 x=w[now]:停在此点 x<w[now]:当有孩子 ...

随机推荐

  1. 如何vue3中使用全局变量,与Vue2的区别

    对比: 在vue2.x中我们挂载全局变量或方法是通过是使用Vue.prototype.$xxxx=xxx的形式来挂载,然后通过this.$xxx来获取挂载到全局的变量或者方法 但是 在vue3.x中显 ...

  2. 快速启动Stable Diffusion WebUI

    快速启动Stable Diffusion WebUI详情    产品文档   输入文档关键字查找   机器学习PAI 产品概述 快速入门 操作指南 准备工作 开通PAI并创建默认工作空间 开通并授权依 ...

  3. Thinking in Java 4th Edition Source Code

    Thinking in Java 4th Edition Source Code Instructions for downloading, installing and testing the so ...

  4. Bug是如何产生的?

    前言 知乎上有一个提问:Bug是如何产生的? ↓↓↓ 今天,我们就这个话题,一起来做个讨论. 个人觉得程序员与BUG的关系,就像空气中的细菌与人的关系一样. 我们不能完全杜绝与它接触,唯一能做的,就是 ...

  5. File --JAVA

    File --JAVA 构造方法 方法 说明 public File (String pathname) 根据文件路径创建对象 public File (String parent, String c ...

  6. Halcon、HDevelop快速入门

    ​ HDevelop基础一 HDevelop概述 HDevelop是一款机器视觉的集成开发环境.下面将对HDevelop的界面内容做一下简单的介绍. 界面介绍 打开HDevelop,将看到以下画面. ...

  7. 手把手教你搭建 Ceph+JuiceFS

    Ceph 提供了对象存储,可作为存储引擎在 JuiceFS 中使用.这一组合非常适合云计算.大数据分析和机器学习等数据密集型应用场景. 在日常部署中可直接通过 Ceph RADOS 配合 JuiceF ...

  8. 基于Qt的Live2D模型显示以及控制

    基于Qt的Live2D模型显示以及控制 基本说明 Live2D官方提供有控制Live2D模型的SDK,而且还提供了一个基于OpenGL的C++项目Example,我们可以基于该项目改成Qt的项目,做一 ...

  9. MongoDB的聚合笔记

    1,聚合 聚合(aggregate)主要用于计算数据,类似sql中的sum().avg(). 常用的表达式如上图. 1.1,aggregate  语法 语法:     db.集合名称.aggregat ...

  10. [ABC263F] Tournament

    Problem Statement $2^N$ people, numbered $1$ to $2^N$, will participate in a rock-paper-scissors tou ...