G. Tree Destruction 【Codeforces Round 991 (Div. 3)】

G. Tree Destruction

在这里插入图片描述

思路

选择路径的中间节点的贡献是度数-2,端点是度数-1,要找最长贡献的路径。
发现一条路径一个点最多连两个边,dfs的时候保留最大和次大单链路径,dfs过程中就可以把经过这个点可能的最长贡献路径给找出来。见代码注释

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define endl '\n'
#define int long long
#define pb push_back
#define pii pair<int, int>
#define FU(i, a, b) for (int i = (a); i <= (b); ++i)
#define FD(i, a, b) for (int i = (a); i >= (b); --i)
const int MOD = 1e9 + 7;
const int INF = 0x3f3f3f3f;
const int N = 2e5 + 5;
vector<int> adj[N];
int w[N];
int ans = -INF;

int dfs(int x, int p) {
    int m1 = -1, m2 = -1; //最大 和 次大单链长度
    for (int e : adj[x]) {
        if (e == p)
            continue;
        int len = dfs(e, x);
        if (len > m2) {
            m2 = len;
        }
        if (m2 > m1)
            swap(m1, m2);
    }
    int tans = w[x]; // 经过x点可能的最长路径(包含分叉)并更新答案
    if (m2 == -1) {
        tans = max(tans, tans + m1);
    } else {
        tans = max(tans, tans + m1 + m2);
    }
    ans = max(tans, ans);
    return max(w[x],w[x]+m1); //返回x为端点单链的最大值
}

void solve() {
    ans=-INF;
    int n;
    cin >> n;
    for (int i = 1; i <= n; i++) {
        adj[i].clear();
        w[i] = -2;
    }
    for (int i = 1; i <= n - 1; i++) {
        int u, v;
        cin >> u >> v;
        adj[u].pb(v);
        adj[v].pb(u);
        w[u]++;
        w[v]++;
    }

    dfs(1, -1);
    cout << ans + 2 << endl;
}

signed main() {
    cin.tie(0)->ios::sync_with_stdio(0);
    int T = 1;
    cin >> T;
    while (T--) {
        solve();
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值