• CF911F Tree Destruction 解题报告


    CF911F Tree Destruction

    题意翻译

    给你一棵树,每次挑选这棵树的两个叶子,加上他们之间的边数(距离),然后将其中一个点去掉,问你边数(距离)之和最大可以是多少.

    输入输出格式

    输入格式:

    The first line contains one integer number n (n) ( (2 le n le 2 imes 10^{5}) ) — the number of vertices in the tree.

    Next (n-1) lines describe the edges of the tree in form (a_{i}),(b_{i})( (1<=a_{i}), (b_{i}<=n) , (a_{i} ot= b_{i}) ). It is guaranteed that given graph is a tree.

    输出格式:

    In the first line print one integer number — maximal possible answer.

    In the next (n-1) lines print the operations in order of their applying in format (a_{i},b_{i},c_{i}) , where (a_{i},b_{i})— pair of the leaves that are chosen in the current operation ( (1 le a_{i}) ,(b_{i} le n) ), (c_{i}) ( (1 le c_{i} le n) , (c_{i}=a_{i}) or (c_{i}=b_{i}) ) — choosen leaf that is removed from the tree in the current operation.

    See the examples for better understanding.


    给了一个贪心的思路:不会产生比最好情况下还要差的结果(由最优推最优)

    首先如果只有一条链,答案是很显然的。

    如果链外有点,点到链的某个端点一定是所有情况的最优贡献,并且删去链外的点对链本身没有影响。

    所以策略就是找到直径的那条链,一个一个删外面的点,最后删直径的。


    Code:

    #include <cstdio>
    #define ll long long
    const int N=2e5+10;
    int Next[N<<1],to[N<<1],head[N],cnt;
    void add(int u,int v)
    {
        to[++cnt]=v,Next[cnt]=head[u],head[u]=cnt;
    }
    int mx=-1,l,r;
    void dfs1(int now,int fa,int d)
    {
        if(mx<d) mx=d,l=now;
        for(int i=head[now];i;i=Next[i])
        {
            int v=to[i];
            if(v!=fa)
                dfs1(v,now,d+1);
        }
    }
    int pre[N];
    void dfs2(int now,int fa,int d)
    {
        if(mx<d) mx=d,r=now;
        for(int i=head[now];i;i=Next[i])
        {
            int v=to[i];
            if(v!=fa)
                pre[v]=now,dfs2(v,now,d+1);
        }
    }
    ll sum;
    int ans[N][2],is[N],n,opt;
    void dfs0(int now,int fa,int d,int s)
    {
        for(int i=head[now];i;i=Next[i])
        {
            int v=to[i];
            if(is[v]||v==fa) continue;
            dfs0(v,now,d+1,s);
        }
        if(!is[now]) ans[++opt][0]=now,ans[opt][1]=s,sum+=1ll*d;
    }
    int main()
    {
        scanf("%d",&n);
        for(int u,v,i=1;i<n;i++)
        {
            scanf("%d%d",&u,&v);
            add(u,v),add(v,u);
        }
        dfs1(1,0,0);
        mx=-1;
        dfs2(l,0,0);
        int now=r,cnt1=0,cnt0=0;
        while(now)
            ++cnt1,is[now]=1,now=pre[now];
        now=r;
        while(now)
        {
            ++cnt0;
            if(((cnt0-1)<<1)>cnt1-1)
                dfs0(now,0,cnt0-1,r);
            else
                dfs0(now,0,cnt1-cnt0,l);
    
            now=pre[now];
        }
        now=r,cnt0=0;
        while(now)
        {
            ++cnt0;
            ans[++opt][0]=now,ans[opt][1]=l,sum+=1ll*(cnt1-cnt0);
            now=pre[now];
        }
        printf("%lld
    ",sum);
        for(int i=1;i<n;i++)
            printf("%d %d %d
    ",ans[i][0],ans[i][1],ans[i][0]);
        return 0;
    }
    
    

    2018.10.11

  • 相关阅读:
    [Zjoi2006]GameZ游戏排名系统
    二逼平衡树
    郁闷的小J
    Dynamic Rankings
    数列[专杀Splay版]
    星际争霸
    半平面交
    自适应辛普森
    7月31日
    规约先行-(三)代码格式
  • 原文地址:https://www.cnblogs.com/butterflydew/p/9770412.html
Copyright © 2020-2023  润新知