zoukankan      html  css  js  c++  java
  • [AGC033F]Adding Edges

    题目链接

    题意

    给定树 $T$ 和图 $G$ ,它们的顶点标号都是最小的 $n$ 个正整数。如果 $a, b, c$(以任意顺序)在树 $T$ 的同一条链上,且 $(a, b), (b, c) in E_G$ ,则在 $G$ 中加入边 $(a, c)$ 。求最终的图的边数。

    题解

    如果只有顺次排列在某链上的 $a, b, c$ 能够推导新边,则有 $(a, b) in G$ 当且仅当存在 $a=v_0, v_1, ldots, v_k=b$ 使得 $(v_0, v_1), (v_1, v_2), ldots, (v_{k-1}, v_k) in E_{G_0}$ 。

    但是事实并不是这样,因此我们考虑把原题给出的边修一修。如果顺次排列在某链上的 $(a, b, c)$ 满足 $(a, b), (a, c) in G$ ,则把 $(a, c)$ 缩短成 $(b, c)$ ,以适应上述简单规则。

    考虑按顺序加入 $G$ 中的边。加入一条边,首先其自身要先根据别的边缩到极短,加入后再缩短其它已有的边。

    不妨假设要加的边缩到极短后为 $(u, v)$ 。

    我们考虑维护 $T$ 以 $1, 2, ldots, n$ 为根时的有根树 $T_1, T_2, ldots, T_n$ 。

    加边时给 $T_u$ 的 $v$ 的子树内所有点 $x$ 打上标记 $v$ ,表示以后若试图加边 $(u, x)$ 就把它缩短一步变成 $(v, x)$ ,反过来对于 $v, u$ 类似操作。

    加边后,还需缩短其它边,这些边应当连接 $u$ 与在 $T_u$ 的 $v$ 的子树内某点,或者反之。为了找到这些边,我们只需要找到标记。

    若 $T_a$ 的 $b$ 上已经有了 $c$ 标记,现又欲打 $d$ 标记,那么在一条链上 $a, d, c, b$ 顺次排列。因此边 $(a, c)$ 会被缩短为 $(d, c)$ ,在下一步中加入这条边。不难发现,接下来若加入 $(a, b)$ ,缩短到 $(d, b)$ 后还会再缩短到 $(c, b)$ ,因此这棵子树内的标记不需要修改。

    因此做法就是在子树内深搜,如果点上没有标记就打上标记,否则记录新边并不再往下搜索。在不同子树中搜索会得到多条新边,用一个列表来维护,每次取出一条待加入的新边加入即可。

    每搜索一个点要么缩短一条边要么标记一个点,而点总共只有 $N^2$ 个,每条边最多被缩短 $N$ 次,总共加的边至多 $NM$ 条。

    接着,为了知道最终图中的边数,我们考虑固定一个端点 $u$ 考虑另一端。这只需要在 $T_u$ 中深搜,并取端点 $b=u$ 。当发现一个表示边的标记时(也就是 $T_b$ 的 $v$ 上标记为 $v$),就说明发现了一条边,搜索其子树时就令 $b=v$ 接着搜索推导的边,退出时该子树时还原 $b$ 。

    因此该算法时空复杂度 $O(N(N+M))$ 。

    实现链接

  • 相关阅读:
    vue项目使用async await 封装 axios
    vue实现预览功能(包括doc,pdf,图片,视频)
    vue中实现下载文件功能
    vue项目中加入拖放排序功能
    Vue项目中生成二维码
    position跟display、overflow、float这些特性相互叠加后会怎么样?
    localStorage使用注意
    webpack 使用总结
    cookie作用域
    语法糖的理解
  • 原文地址:https://www.cnblogs.com/nealchen/p/AGC033F.html
Copyright © 2011-2022 走看看