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
答案为边权之和。
不妨考虑最优答案应当是怎样的。
每一条权值较小的边应当被尽量少的次数经过,所以应当尽量先取权值大的边。
想一想就可以知道:
最优答案一定不会大于边权之和。
因为对于任何一个排列,每条边至少会经过一次。
存在一种构造方式,构造出边权之和。
使最大边权所连的点入队,不断取出队中的点所连的最大边权,并将新点入队。
这样形成的排列,边权不断减小,所以每条边都被充分利用,所以是正确的。