Subway
Memory limit: 128 MB
A certain city has been coping with subway construction for a long time. The finances have been mismanaged and the costs have been underestimated to such extent that no funds were foreseen for the purchase of trains. As a result, too many stations and only some of the planned tunnels have been built - barely enough to allow a connection between any two stations to exist. The number of tunnels (each of them is bidirectional) is one less than the number of stations built. From the remaining funds only a handful of trains have been acquired.
To save their face the board of directors have asked you to plan subway routes in such a way as to allow maximal number of stations to be connected. Each train travels on a specified route. The routes cannot branch (no three tunnels starting at a single station may belong to the same route). Distinct routes may comprise the same station or tunnel.
Task
Write a programme which:
- reads a description of the tunnel system and the number of subway lines, which are to be planned from the standard input,
- calculates the maximal number of stations which can be covered by the specified number of subway lines,
- writes the outcome to the standard output.
Input
The first line of the standard input contains two integers
and
(
,
) separated by a single space. The number
denotes the number of stations and the number
denotes the number of subway lines, which are to be planned. The stations are numbered from 1 to
.
Each of the following
lines contains two distinct integers separated by a single space. The numbers
in the
-th line denote the numbers of stations connected by
-th tunnel.
Output
The first and only line of the standard output should contain a single integer denoting the maximal number of stations which can be covered by train routes.
For the input data:17 3the correct outcome is:
1 2
3 2
2 4
5 2
5 6
5 8
7 8
9 8
5 10
10 13
13 14
10 12
12 11
15 17
15 16
15 1013![]()
The figure represents the tunnel system (with subway routes marked) in one of the optimal configurations.
(from: http://www.oi.edu.pl/php/show.php?ac=e180602&module=show&file=zadania/oi13/met&print=yes )
首先证明,存在最优解,使得所有路径形成一棵树:
假设路径由两部分组成,则可以找到两个点V1、V2,使得X1-V1-Y1、X2-V2-Y2均为一条路径,那么连接V1、V2,并把X1-V1-V2-X2、Y1-V1-V2-Y2作为两条新路经,路径总数不变,解不会变差。
其次,对于原树上的一条最长链, 一定存在一个最优解,包含这条链:
如图,设X0,X1,...,Xn是当前解中的一条链,Y0,Y1,..Ym是原树的最长链(m>n 且 X0、Xn、Y0、Ym为叶结点),Xk是一个度不小于3的节点。
不妨设在X0..Xk,Xk..Xn中较短链为X0..Xk,Y0..Yp,Yp..Ym中较长链为Y0..Yp,那么沿Xn向父节点删除节点直到一个度不小于3的节点,再把Xk-Yp-...-Y0加入,得到的新解不比原来的差。
如果要用k条路径覆盖一棵树,叶结点最多2k个;而如果有2k个叶结点,通过归纳法可以证明,一定存在一个用k条路径覆盖所有节点的方案。因此可以把最长链的一个端点作为根建立有根树,原问题转化为从根出发寻找2l-1条路径使得覆盖的点最多,可以贪心解决。我的实现是O(n + l log n)的,其实还存在O(n)的实现。
附上源代码: