zoukankan      html  css  js  c++  java
  • cf 911F 树的直径+贪心

    $des$ 

    给定一棵 n 个节点的树,你可以进行 n ? 1 次操作,每次操作步骤如下:
    选择 u,v 两个度数为 1 的节点。
    将 u,v 之间的距离加到 ans 上。
    将 u 从树上删除。
    求一个操作序列使得 ans 最大。

    $sol$

    先把直径拿出来,将直径外的点一个一个的和直径中的某一个端点配对并删掉。最
    后再将直径删掉。这样就是对的。
    如果当前直径外已经没有点了,那么显然只能将直径的端点删掉。否则一定不会去
    删直径的端点。
    因为先删一个直径外的点再删直径端点一定是不劣于先删直径端点再删这个直径外
    的点的。

    $code$

    #include <bits/stdc++.h>
    
    using namespace std;
    
    #define gc getchar()
    inline int read() {
        int x = 0; char c = gc;
        while(c < '0' || c > '9') c = gc;
        while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = gc;
        return x;
    
    }
    
    #define LL long long
    #define Rep(i, a, b) for(int i = a; i <= b; i ++)
    #define E exit(0)
    
    const int N = 2e5 + 10;
    
    int disa[N], disb[N], fa[N], A[N], topp[N], size[N], son[N], deep[N], sonjs[N];
    bool Be_calc[N], vis[N], is_chain[N];
    int Cut[N], js;
    
    struct Node {int v, nxt;} G[N << 1];
    int head[N], cnt;
    
    int n, One, Tow;
    
    void Link(int u, int v) {
        G[++ cnt].v = v; G[cnt].nxt = head[u]; head[u] = cnt;
    }
    
    int Bfs(int start, int dis[]) {
        queue <int> Q;
        memset(vis, 0, sizeof vis);
        dis[start] = 0;
        vis[start] = 1;
        Q.push(start);
        while(!Q.empty()) {
            int topp = Q.front();
            Q.pop();
            for(int i = head[topp]; ~ i; i = G[i].nxt) {
                int v = G[i].v;
                if(!vis[v]) {
                    dis[v] = dis[topp] + 1;
                    vis[v] = 1;
                    Q.push(v);
                }
            }
        }
        int ret, retdis = -1;
        Rep(i, 1, n) if(dis[i] > retdis) ret = i, retdis = dis[i];
        return ret;
    }
    
    void Dfs1(int u, int f_, int dep) {
        fa[u] = f_, deep[u] = dep; size[u] = 1;
        for(int i = head[u]; ~ i; i = G[i].nxt) {
            int v = G[i].v;
            if(v == f_) continue;
            sonjs[u] ++;
            Dfs1(v, u, dep + 1);
            size[u] += size[v];
            if(size[v] > size[son[u]]) son[u] = v;
        }
    }
    
    void Dfs2(int u, int tp) {
        topp[u] = tp;
        if(!son[u]) {
            Cut[++ js] = u;
            return ;
        }
        Dfs2(son[u], tp);
        for(int i = head[u]; ~ i; i = G[i].nxt) {
            int v = G[i].v;
            if(v != fa[u] && v != son[u]) Dfs2(v, v);
        }
    }
    
    inline int Lca(int x, int y) {
        int tpx = topp[x], tpy = topp[y];
        while(tpx != tpy) {
            if(deep[tpx] < deep[tpy]) swap(x, y), swap(tpx, tpy);
            x = fa[tpx], tpx = topp[x];
        }
        if(deep[x] < deep[y]) swap(x, y);
        return y;
    }
    
    void Find_chain() {
        int lca = Lca(One,Tow);
        int tmp1 = One, tmp2 = Tow;
        while(tmp1 != lca) {
            is_chain[tmp1] = 1;
            tmp1 = fa[tmp1];
        }
        while(tmp2 != lca) {
            is_chain[tmp2] = 1;
            tmp2 = fa[tmp2];
        }
        is_chain[lca] = 1;
    }
    
    int o_1[N], o_2[N], o_3[N], tot;
    
    int main() {
        n = read();
        Rep(i, 1, n) head[i] = -1;
        Rep(i, 1, n - 1) {
            int u = read(), v = read(); Link(u, v), Link(v, u);
        }
        
        One = Bfs(1, disa);
        Tow = Bfs(One, disa);
        Bfs(Tow, disb);
        Dfs1(One, 0, 1);
        Dfs2(One, One);
        Find_chain();
    
        LL Answer = 0;
        Rep(i, 1, js) {
            if(is_chain[Cut[i]] || Be_calc[Cut[i]]) continue;
            int now = Cut[i];
            
            while(!Be_calc[now] && !is_chain[now] && !sonjs[now]) {
                if(disa[now] > disb[now]) {
                    o_1[++ tot] = One, o_2[tot] = now, o_3[tot] = now;
                    Answer += disa[now];
                } else {
                    o_1[++ tot] = Tow, o_2[tot] = now, o_3[tot] = now;
                    Answer += disb[now];
                }
                Be_calc[now] = 1;
                now = fa[now];
                sonjs[now] --;
            }
        }
        
        int lca = Lca(One, Tow);
        
        while(One != lca) {
            o_1[++ tot] = One, o_2[tot] = Tow, o_3[tot] = One;
            Answer += disb[One];
            One = fa[One];
        }
        while(Tow != lca) {
            o_1[++ tot] = Tow, o_2[tot] = lca, o_3[tot] = Tow;
            Answer += (deep[Tow] - deep[lca]);
            Tow = fa[Tow];
        }
        
        cout << Answer << "
    ";
        Rep(i, 1, tot) {
            cout << o_1[i] << " " << o_2[i] << " " << o_3[i] << "
    ";
        }
        return 0;
    }
  • 相关阅读:
    IntelliJ IDEA 2020.1.1中java web项目的配置
    Js查漏补缺10-数组、栈、队列、回调函数等
    Js查漏补缺09-this对象
    Js查漏补缺08-闭包
    Js查漏补缺07-匿名函数应用到的框架
    Js查漏补缺06-匿名函数的用法
    Js查漏补缺05-函数
    Js查漏补缺04-Object类型
    Js查漏补缺03-循环结构
    Runnabler
  • 原文地址:https://www.cnblogs.com/shandongs1/p/9770887.html
Copyright © 2011-2022 走看看