二叉苹果树
思路
一般的树都是对节点进行统计或者计算,但是这题是对边进行统计计算,所以要稍加特殊处理,貌似我这种方法处理的比较微妙。
我们按照传统定义表示节点连接了条边的果子数量最大值,所以我们显然可以对当前节点进行统计枚举:
for(int i) for(int j)
两重循环,表示的是该节点当前已经统计的子树节点个数,表示改节点当前正在枚举的子树节点,然后通过加减组合来更新我们的答案,这个地方有一个特殊处理,具体看代码。
代码
/* Author : lifehappy */ #pragma GCC optimize(2) #pragma GCC optimize(3) #include <bits/stdc++.h> #define mp make_pair #define pb push_back #define endl '\n' #define mid (l + r >> 1) #define lson rt << 1, l, mid #define rson rt << 1 | 1, mid + 1, r #define ls rt << 1 #define rs rt << 1 | 1 using namespace std; typedef long long ll; typedef unsigned long long ull; typedef pair<int, int> pii; const double pi = acos(-1.0); const double eps = 1e-7; const int inf = 0x3f3f3f3f; inline ll read() { ll f = 1, x = 0; char c = getchar(); while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); } while(c >= '0' && c <= '9') { x = (x << 1) + (x << 3) + (c ^ 48); c = getchar(); } return f * x; } const int N = 110; int head[N], nex[N << 1], to[N << 1], value[N << 1], cnt = 1; int n, m, dp[N][N], sz[N]; void add(int x, int y, int w) { to[cnt] = y; nex[cnt] = head[x]; value[cnt] = w; head[x] = cnt++; } void dfs(int rt, int fa) { sz[rt] = 1; for(int i = head[rt]; i; i = nex[i]) { if(to[i] == fa) continue; dfs(to[i], rt); for(int j = sz[rt] - 1; ~j; j--) { //外重循环是枚举改节点已经可以连接的最多的边,这个个数量就是sz[rt] - 1了 for(int k = sz[to[i]] - 1; ~k; k--) { //当前枚举到的儿子节点是否与该节点连接,同样道理数量也是sz[to[i]] - 1 if(j + k + 1 <= m) {//两个连通块连接,所以还要加上一条边。 dp[rt][j + k + 1] = max(dp[rt][j + k + 1], dp[rt][j] + dp[to[i]][k] + value[i]); } } } sz[rt] += sz[to[i]]; } } int main() { // freopen("in.txt", "r", stdin); // freopen("out.txt", "w", stdout); // ios::sync_with_stdio(false), cin.tie(0), cout.tie(0); n = read(), m = read(); for(int i = 1; i < n; i++) { int x = read(), y = read(), w = read(); add(x, y, w); add(y, x, w); } dfs(1, 0); int ans = 0; for(int i = 1; i <= m; i++) { ans = max(ans, dp[1][i]); } cout << ans << endl; return 0; }