zoukankan      html  css  js  c++  java
  • 模拟62 题解

    A. Graph

    在树的情况下,答案是显然的。

    一次dfs,尽量将子树内不同的边合并就可以了。

    考虑非树的情况,可以生成一棵树。

    将非树边任意加在一个端点上,视作点权加一。

    对于树上的每一个点,先考虑它的子节点,子节点的父边尽量在子节点处作连接节点使用。

    如果子节点的父边还没有被使用,那么只能在父节点处使用。

    同时将该节点的点权不断使用。

    正确性是显然的,因为对于每一个联通块,都可以形成足够的边对。

    B. Permutation

    考虑怎样的一些点对$(i,j)$,它们之间不能交换。

    将所有不能交换的点对建边,跑出最优的拓扑序就是最优解。

    然而这样建图是$n^2$的,很难优化。

    考虑换一种方式建边。

    因为原序列是一个排列,可以处理出数组$pos$,使$pos_{a_i}=i$

    于是原图中的边在$pos$数组下标的形式下转化为了简单的形式。

    $$i<j$$

    $$abs(pos_i-pos_j)<k$$

    然而暴力建边仍然$n^2$,

    一个很好的性质是:在$pos$的限制下,每个点建边区间范围是相同的。

    所以倒序建边,每个点只要向$pos$意义下左右两侧最小的j建边就可以了。

    然而值得注意的是,对于一个排列,$pos$意义下更小,不意味着原数组更小。

    本题中实际上是利用了特殊性质,因为会不断交换合法的点,使得不存在使原数组更小的情况。

    C. Tree

    答案为边权之和。

    不妨考虑最优答案应当是怎样的。

    每一条权值较小的边应当被尽量少的次数经过,所以应当尽量先取权值大的边。

    想一想就可以知道:

    最优答案一定不会大于边权之和。

    因为对于任何一个排列,每条边至少会经过一次。

    存在一种构造方式,构造出边权之和。

    使最大边权所连的点入队,不断取出队中的点所连的最大边权,并将新点入队。

    这样形成的排列,边权不断减小,所以每条边都被充分利用,所以是正确的。

  • 相关阅读:
    面试问题
    知识点整合
    前端错误
    基于.NET平台常用的框架整理
    BFC和haslayout
    javascript面向对象
    javascript变量的作用域
    2014-05-26 总结
    2014-05-23 总结
    PHP实现mvc模式的思想
  • 原文地址:https://www.cnblogs.com/skyh/p/11628575.html
Copyright © 2011-2022 走看看