[CF 1238F] The Maximum Subtree 树DP

题意

给定一颗树,求这个树的最大子树的大小,要求这个子树是一个good-tree。

good-tree的定义是:树上每个节点表示一个一维区间,当两个节点的区间有重叠时,两个节点间存在一条边。

题解

不可能画出一个十字形的树,每个方向包含两个节点。

通过分析可以发现,这个子树是这个树的一条链,然后允许这条链上的点带上直接连接的点。

然后就转化为树上求最长链的DP问题。

// #pragma GCC optimize(2)
// #pragma GCC optimize(3)
// #pragma GCC optimize(4)
#include <bits/stdc++.h>
//#include <unordered_set>
//#include <unordered_map>
// #include<bits/extc++.h>
// using namespace __gnu_pbds;
using namespace std;
#define pb push_back
#define fi first
#define se second
#define debug(x) cerr << #x << " := " << x << endl;
#define bug cerr << "-----------------------" << endl;
#define FOR(a, b, c) for (int a = b; a <= c; ++a)

typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;

const int inf = 0x3f3f3f3f;
const ll inff = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + 7;

template <typename T>
inline T read(T &x) {
    x = 0;
    int f = 0;
    char ch = getchar();
    while (ch < '0' || ch > '9') f |= (ch == '-'), ch = getchar();
    while (ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar();
    return x = f ? -x : x;
}

/**********showtime************/
const int maxn = 3e5 + 9;
vector<int> mp[maxn];
int dp[maxn];
int ans = 0;

void dfs(int u, int fa) {
    int sz = mp[u].size();
    dp[u] = sz;
    for (int v : mp[u]) {
        if (v == fa) continue;
        dfs(v, u);
        ans = max(ans, dp[u] + dp[v]);
        dp[u] = max(dp[u], dp[v] + sz - 1);
    }
}

int main() {
    int T;
    scanf("%d", &T);
    while (T--) {
        int n;
        scanf("%d", &n);
        for (int i = 1; i <= n; i++) mp[i].clear();
        for (int i = 1; i < n; i++) {
            int u, v;
            scanf("%d%d", &u, &v);
            mp[u].pb(v);
            mp[v].pb(u);
        }
        ans = 0;
        dfs(1, 1);
        printf("%d\n", ans);
    }
    return 0;
}
View Code

 

posted @ 2019-11-02 19:46  ckxkexing  阅读(198)  评论(0编辑  收藏  举报