[SDOI2018]战略游戏

这题是道路相遇题解)的升级版,询问的两个点变成了\(S\)个点。

LG传送门

还是先建出圆方树,考虑对于询问的\(S\)个点,答案就是圆方树上能包含这些点的最小连通块中的圆点个数减去\(S\)。问题变成了怎样求这样的连通块中的圆点个数,直接给结论吧:先搞出树的dfs序,把询问的点按dfs序从小到大排一遍序,每次把答案加上第\(i\)和第\(i + 1\)个点之间的圆点个数,但是不算lca,再加上第\(1\)个和第\(S\)个点之间的圆点个数,然后除以二就得到了这个连通块内不包括整个连通块的lca的圆点个数,可以证明这个连通块内除了lca的所有点都被算了两次,最后判断一下lca是不是圆点,减去\(S\)就是答案。

实测树剖比倍增快很多。

  1. #include <cstdio>
  2. #include <cctype>
  3. #include <cstring>
  4. #include <algorithm>
  5. #define R register
  6. #define I inline
  7. #define B 10000000
  8. using namespace std;
  9. const int N = 400003;
  10. char buf[B], *p1, *p2;
  11. I char gc() { return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, B, stdin), p1 == p2) ? EOF : *p1++; }
  12. I int rd() {
  13. R int f = 0; R char c = gc();
  14. while (c < 48 || c > 57)
  15. c = gc();
  16. while (c > 47 && c < 58)
  17. f = f * 10 + (c ^ 48), c = gc();
  18. return f;
  19. }
  20. int h[N], H[N], sta[N], dfn[N], low[N], vis[N], fa[N], dep[N], siz[N], son[N], top[N], dis[N], q[N], n, c, tim, cnt, stp;
  21. struct edge { int s, g; }e[N], E[N];
  22. I void add(int x, int y) { e[++c] = (edge){h[x], y}, h[x] = c; }
  23. I void Add(int x, int y) { E[++c] = (edge){H[x], y}, H[x] = c; }
  24. I int min(int x, int y) { return x < y ? x : y; }
  25. I int cmp(int x, int y) { return dfn[x] < dfn[y]; }
  26. void dfs(int x) {
  27. vis[sta[++stp] = x] = 1, dfn[x] = low[x] = ++tim;
  28. for (R int i = h[x], y, z; i; i = e[i].s)
  29. if (!dfn[y = e[i].g]) {
  30. dfs(y), low[x] = min(low[x], low[y]);
  31. if (low[y] >= dfn[x]) {
  32. Add(++cnt, x), Add(x, cnt);
  33. do {
  34. vis[z = sta[stp--]] = 0, Add(cnt, z), Add(z, cnt);
  35. } while (z ^ y);
  36. }
  37. }
  38. else
  39. low[x] = min(low[x], dfn[y]);
  40. }
  41. void dfs1(int x, int f) {
  42. fa[x] = f, dep[x] = dep[f] + 1, siz[x] = 1, dis[x] = dis[f] + (x <= n);
  43. for (R int i = H[x], y, m = 0; i; i = E[i].s)
  44. if ((y = E[i].g) ^ f) {
  45. dfs1(y, x), siz[x] += siz[y];
  46. if (siz[y] > m)
  47. m = siz[x], son[x] = y;
  48. }
  49. }
  50. void dfs2(int x, int r) {
  51. dfn[x] = ++tim, top[x] = r;
  52. if (son[x])
  53. dfs2(son[x], r);
  54. for (R int i = H[x], y; i; i = E[i].s)
  55. if ((y = E[i].g) ^ fa[x] && y ^ son[x])
  56. dfs2(y, y);
  57. }
  58. I int lca(int x, int y) {
  59. while (top[x] ^ top[y])
  60. dep[top[x]] > dep[top[y]] ? x = fa[top[x]] : y = fa[top[y]];
  61. return dep[x] < dep[y] ? x : y;
  62. }
  63. I int query(int x, int y) { return dis[x] + dis[y] - (dis[lca(x, y)] << 1); }
  64. int main() {
  65. R int T = rd(), m, Q, S, i, x, y, ans;
  66. while (T--) {
  67. memset(h, 0, sizeof h), memset(H, 0, sizeof H), memset(son, 0, sizeof son), memset(dfn, 0, sizeof dfn);
  68. cnt = n = rd(), m = rd(), c = 0;
  69. for (i = 1; i <= m; ++i)
  70. x = rd(), y = rd(), add(x, y), add(y, x);
  71. c = tim = stp = 0, dfs(1), tim = 0, dfs1(1, 0), dfs2(1, 1), Q = rd();
  72. while (Q--) {
  73. S = rd();
  74. for (i = 1; i <= S; ++i)
  75. q[i] = rd();
  76. sort(q + 1, q + S + 1, cmp), ans = query(q[1], q[S]);
  77. for (i = 2; i <= S; ++i)
  78. ans += query(q[i - 1], q[i]);
  79. printf("%d\n", (ans >> 1) - S + (lca(q[1], q[S]) <= n));
  80. }
  81. }
  82. return 0;
  83. }

[SDOI2018]战略游戏 圆方树,树链剖分的更多相关文章

  1. bzoj5315/luoguP4517 [SDOI2018]战略游戏(圆方树,虚树)

    bzoj5315/luoguP4517 [SDOI2018]战略游戏(圆方树,虚树) bzoj Luogu 题目描述略(太长了) 题解时间 切掉一个点,连通性变化. 上圆方树. $ \sum |S| ...

  2. Luogu4606 SDOI2018 战略游戏 圆方树、虚树、链并

    传送门 弱化版 考虑到去掉一个点使得存在两个点不连通的形式类似割点,不难想到建立圆方树.那么在圆方树上对于给出的关键点建立虚树之后,我们需要求的就是虚树路径上所有圆点的数量减去关键点的数量. 因为没有 ...

  3. BZOJ5329:[SDOI2018]战略游戏(圆方树,虚树)

    Description 省选临近,放飞自我的小Q无心刷题,于是怂恿小C和他一起颓废,玩起了一款战略游戏. 这款战略游戏的地图由n个城市以及m条连接这些城市的双向道路构成,并且从任意一个城市出发总能沿着 ...

  4. BZOJ.5329.[SDOI2018]战略游戏(圆方树 虚树)

    题目链接 显然先建圆方树,方点权值为0圆点权值为1,两点间的答案就是路径权值和减去起点终点. 对于询问,显然可以建虚树.但是只需要计算两关键点间路径权值,所以不需要建出虚树.统计DFS序相邻的两关键点 ...

  5. Luogu P4606 [SDOI2018] 战略游戏 圆方树 虚树

    https://www.luogu.org/problemnew/show/P4606 把原来的图的点双联通分量缩点(每个双联通分量建一个点,每个割点再建一个点)(用符合逻辑的方式)建一棵树(我最开始 ...

  6. [bzoj5329] P4606 [SDOI2018]战略游戏

    P4606 [SDOI2018]战略游戏:广义圆方树 其实会了圆方树就不难,达不到黑,最多算个紫 那个转换到圆方树上以后的处理方法,画画图就能看出来,所以做图论题一定要多画图,并把图画清楚点啊!! 但 ...

  7. 洛谷P4606 [SDOI2018]战略游戏 [广义圆方树]

    传送门 思路 先考虑两点如何使他们不连通. 显然路径上所有的割点都满足条件. 多个点呢?也是这样的. 于是可以想到圆方树.一个点集的答案就是它的虚树里圆点个数减去点集大小. 可以把点按dfs序排序,然 ...

  8. 洛谷P4606 [SDOI2018]战略游戏 【圆方树 + 虚树】

    题目链接 洛谷P4606 双倍经验:弱化版 题解 两点之间必经的点就是圆方树上两点之间的圆点 所以只需建出圆方树 每次询问建出虚树,统计一下虚树边上有多少圆点即可 还要讨论一下经不经过根\(1\)的情 ...

  9. [SDOI2018]战略游戏(圆方树+虚树)

    喜闻乐见的圆方树+虚树 图上不好做,先建出圆方树. 然后答案就是没被选到的且至少有两条边可以走到被选中的点的圆点的数量. 语文不好,但结论画画图即可得出. 然后套路建出虚树. 发现在虚树上DP可以得出 ...

随机推荐

  1. PHPredis安装

    一.PHPredis下载链接:https://pan.baidu.com/s/1bz0EaJgDpp2ADQJCJOHJGA 二.解压并进入目录 三.发现没有configure文件,需要安装autoc ...

  2. 铁乐学python_day24_面向对象进阶1_内置方法

    铁乐学python_day24_面向对象进阶1_内置方法 题外话1: 学习方法[wwwh] what where why how 是什么,用在哪里,为什么,怎么用 学习到一个新知识点的时候,多问问上面 ...

  3. map filter 的func 放在前面

    map    filter      的func 放在前面 sorted 在后 (    iter..  ,       key=function')

  4. 装office系统软件

    在电脑里搜索 SW_DVD5_Office_Professional_Plus_2010w_SP1_64Bit_ChnSimp_CORE_MLF_X17-76742 如果已经安装过了,有错误,直接进行 ...

  5. PHP设计模式系列 - 装饰器

    什么是装饰器 装饰器模式,对已有对象的部分内容或者功能进行调整,但是不需要修改原始对象结构,可以使用装饰器设 应用场景 设计一个UserInfo类,里面有UserInfo数组,用于存储用户名信息 通过 ...

  6. php实现动态随机验证码机制(CAPTCHA)

    php实现动态随机验证码机制 验证码(CAPTCHA)是“Completely Automated Public Turing test to tell Computers and Humans Ap ...

  7. 【bzoj 4710】 [Jsoi2011]分特产

    题目 容斥加组合计数 显然答案是 \[\sum_{i=0}^n(-1)^i\binom{n}{i}f_{n-i}\] \(f_i\)表示至多有\(i\)个人没有拿到特产 考虑求\(f\) 发现\(m\ ...

  8. jquery的fadeTo方法的淡入淡出轮播图插件

    由于对基于jquery的简单插件开发有了一定的了解,慢慢的也对基于jquery的插件开发有了兴趣,在上班结束之后就研究各种插件的思路逻辑.最近开发了一款基于jquery的fadeTo方法的轮播图插件, ...

  9. Java基础加强之代理

    本文引用自 http://www.cnblogs.com/xdp-gacl/p/3971367.html 1.什么是代理 动态代理技术是整个java技术中最重要的一个技术,它是学习java框架的基础, ...

  10. 使用nginx替换Ingress

    总感觉k8s Ingress 不可控, 所以使用nginx 替换Ingress,还是比较简单的. apiVersion: extensions/v1beta1 kind: DaemonSet meta ...