参考红宝书
对除 1 号点顶点外的点集,求一次最小生成森林,对于最小生成森林的联通分量,选择最短的一条边与 1 号点相连。设此时 1 号点的度为 (k_0),如果 (k_0lt L) 则无解 (L为1号顶点的规定度)
然后通过可行交换来增加 1 号点的度,每次尝试加入一条和 1 号点相连的边,然后删去所形成的环上面的最长边。
此题点数为 5000,对于每次交换,可以用树形DP求出所有点到 1 号点的最长边。每次选择增量最小的边去交换,直到 (k_0) 达到 L
在实现中的一些困难:
- 答案要求构成生成树的边序号,所以加边时要保留原边序号信息
- 树形DP要找到每个点到 根 的最长路大小,以及对应边的序号
- 如果一个点与根直接相连,可以把这个边序号保留下来(下面代码中用path数组保留),方便之后做替换用
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf = 0x3f3f3f3f;
#define dbg(x...) do { cout << "