题目
设T为一带权树,树中的每个边的权都为整数。又设S为T的一个顶点的子集,从T中删除S中的所有结点,则得到一个森林,记为T/S。如果T/S中所有树从根到叶子节点的路径长度都不超过d,则称T/S是一个d森林。设计一个算法求T的最小顶点集合S,使T/S为一个d森林。
题解
* d森林
*/
#include<bits/stdc++.h>
#define MAXN 10000 + 10
using namespace std;
int parent[MAXN], leaf[MAXN], parlen[MAXN], deg[MAXN], cut[MAXN], dist[MAXN];
int count (int d) {
int total = 0;
for (int i = 1; i <= leaf[0]; i++) {
if (leaf[i] != 1) {
int plen = parlen[leaf[i]], par = parent[leaf[i]];
if (cut[par] < 1 && dist[leaf[i]] + plen > d) {
total++;
cut[par] = 1;
par = parent[par];
} else if (cut[par] < 1 && dist[par] < dist[leaf[i]] + plen)
dist[par] = dist[leaf[i]] + plen;
if (--deg[par] == 0)
leaf[++leaf[0]] = par;
}
}
return total;
}
int main() {
int n;
cout << "Please input the number of vertex: ";
cin >> n;
for (int i = 1; i <= n; i++) {
cout << "Please input the message of the " << i + 1 << "th vertex:" << endl;
cout << "\tThe number of associated vertex is: ";
cin >> deg[i];
cout << "\t\tThe associated edges are: ";
for (int j = 0; j < deg[i]; j++) {
int p, len;
cin >> p >> len;
parent[p] = i;
parlen[p] = len;
}
if (deg[i] == 0)leaf[++leaf[0]] = i;
}
int d;
cin >> d;
int result = count (d);
cout << result;
return 0;
}