[IPSC 2008](I. Inventing Test Data) Summary

Inventing Test Data
图论
完全图中任意两个结点间都有边,为方便起见我们把属于生成树的边称为树边,其它的边称为余边,用w(a,b)表示边(a,b)的权。我们的任务是给所有余边的赋予尽可能小的权,使得给定的生成树为完全图的唯一最小生成树。考虑某条余边(a,b),(a,b)显然不属于生成树。对于a、b在生成树中的路径path(a,b)上的任意一条边(u,v),一定有w(u,v)=w(a,b),那么将(u,v)从生成树中删去,再将(a,b)加入生成树会形成合法的生成树,并且新生成树的所有边劝和不会大于给定生成树,这与原生成树为唯一最小生成树矛盾。这样我们得到结论:所有余边(a,b)的权一定大于生成树中连接(a,b)的路径上每条边的权。类似的,容易证明这个结论的逆命题成立。现在思路已经很清晰了:对于每个余边(a,b),为它赋予生成树中连接a与b的路径上最大边权值加一,即满足条件的最小权值。借助初始化,这个算法朴素实现的时间复杂度为O(n2),显然不能满足要求。
我们可以模仿Kruskal算法来得到一个时间复杂度为O(nlogn)的算法。初始时把所有边都去掉,每个结点独为一个连通分量,然后按照边权从小到大的顺序处理输入数据给出的生成树的每一条边,这个过程中不必像Kruskal算法那样判断是否产生环,因为本题中我们所处理的边本身就形成生成树。这样所处理的每条边(a,b)一定连接两个不同的连通分量p、q,由于我们是按照边权从小到大的顺序处理的,因此w(a,b)一定大于任何p或q中边的权,所有的余边(u,v)(u属于p且v属于q)都应该被赋予权值w(a,b)+1。借助并查集,很容易维护所有连通分量之间的关系。这个O(nlogn)的算法常数较小,完全可以承受极限数据。

1
2
3
4
5
6
7
8
9
10
11
12
#include 
 
using namespace std;
 
const int MAXN=100001;
int father[MAXN],size[MAXN];
struct edge
{
	int a,b,w;
	bool operator<(const edge &other) const
	{
		return w
Posted in IPSC. Tags: , . No Comments »