zoukankan      html  css  js  c++  java
  • Codeforces1238F. The Maximum Subtree(树形dp)

    题目链接:传送门

    思路:

    题意说用线段的相交作为边,来构造树,所以不存在大于等于3个的线段两两相交,否则会构成环。因而构造出的树中,每个点最多只会与2个度大于1的节点相邻。

    不妨把1设为树根,用degu表示原树中节点u的度,ans表示答案。

    用fu表示:假设以u为根的子树,已经有一条边连向了一个度大于1的点时,所能构成的最大的“子树的子树”的大小,则有:

    f= 1,if degu=1。叶子本身就是一个点,大小为1。

    fu = max{v是u的子节点 | fv} + degu-2 + 1。所有孩子中选一个fv最大的作为第2个度大于1的节点(第1个已经连出去了),这时相邻的点已经用掉2个了,剩余其他的所有相邻的点的数量为degu-2,再算上u本身。

    这样处理完之后答案就很好算了。

    对于一个节点u的子节点v中,fv最大的两个之和+degu-2+1,就是答案的一种可能。

    (对答案的更新,代码中不是这样写的。我在更新答案的时候,利用了fu已经保存之前(fv+degu-2+1)的最大值相关信息的特点,直接用fu来更新答案了)

    代码实现:O(N)

    #include <bits/stdc++.h>
    #define fast ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
    #define N 300005
    #define M 300005
    #define INF 0x3f3f3f3f
    #define mk(x) (1<<x) // be conscious if mask x exceeds int
    #define sz(x) ((int)x.size())
    #define upperdiv(a,b) (a/b + (a%b>0))
    #define mp(a,b) make_pair(a, b)
    #define endl '
    '
    #define lowbit(x) (x&-x)
    
    using namespace std;
    typedef long long ll;
    typedef double db;
    
    /** fast read **/
    template <typename T>
    inline void read(T &x) {
        x = 0; T fg = 1; char ch = getchar();
        while (!isdigit(ch)) {
            if (ch == '-') fg = -1;
            ch = getchar();
        }
        while (isdigit(ch)) x = x*10+ch-'0', ch = getchar();
        x = fg * x;
    }
    template <typename T, typename... Args>
    inline void read(T &x, Args &... args) { read(x), read(args...); }
    
    int tot = 0;
    int head[N], nxt[M<<1], ver[M<<1], deg[N];
    void addEdge(int u, int v) {
        nxt[++tot] = head[u], ver[tot] = v, head[u] = tot;
        deg[u]++;
    }
    
    int f[N];
    bool vis[N];
    int ans;
    void dfs(int u) {
        vis[u] = true;
        f[u] = deg[u];
        for (int i = head[u]; i != -1; i = nxt[i]) {
            int v = ver[i];
            if (vis[v])
                continue;
            dfs(v);
            ans = max(ans, f[u] + f[v]);
            f[u] = max(f[u], f[v] + deg[u]-2 + 1);
        }
    }
    int main()
    {
        int q; read(q);
        while (q--) {
            int n; read(n);
            ans = 0;
            tot = 0;
            for (int i = 1; i <= n; i++) {
                head[i] = -1;
                deg[i] = 0;
                f[i] = 0;
                vis[i] = false;
            }
            int u, v;
            for (int i = 1; i <= n-1; i++) {
                read(u, v);
                addEdge(u, v);
                addEdge(v, u);
            }
            dfs(1);
            cout << ans << endl;
        }
        return 0;
    }
    View Code
  • 相关阅读:
    Openssl s_time命令
    Openssl speed命令
    Openssl s_client命令
    Openssl s_server命令
    Openssl smime命令
    关于静态与非静态之具体总结
    C++游戏系列2:角色装备武器
    POJ 2398 Toy Storage(计算几何)
    Oracle核心技术 笔记(该书读得不细致,须要找时间再细读~~)
    还在为开发APP发愁? 这里就有现成通用的代码!
  • 原文地址:https://www.cnblogs.com/Lubixiaosi-Zhaocao/p/11701465.html
Copyright © 2011-2022 走看看