CF.911F.Tree Destruction(构造 贪心)

题目链接

\(Description\)

一棵n个点的树,每次可以选择树上两个叶子节点并删去一个,得到的价值为两点间的距离
删n-1次,问如何能使最后得到的价值最大,并输出方案

\(Solution\)

树上距离,求最大,可以考虑下树的直径
假如已知树的直径u->v,那么任意一点x到达其他点的最远距离就是u,v中一点(如果不是这样,那直径一定可以更长而不是uv)
假设x距u最远,那肯定是删x
删直径上的点(直径端点)会导致一些点取不到最远距离
既然这样按顺序删非直径上的点,最后删直径端点

#include<cstdio>
#include<cctype>
#include<algorithm>
#define gc() getchar()
const int N=2e5+5;

int n,U,V,mxdis,fa[N],dis[N][2],cnt,D[N],Enum,H[N],to[N<<1],nxt[N<<1];
long long res;
bool Is_d[N];
struct Triple
{
    int u,v,w;
}ans[N];

inline int read()
{
    int now=0,f=1;register char c=gc();
    for(;!isdigit(c);c=gc()) if(c=='-') f=-1;
    for(;isdigit(c);now=now*10+c-'0',c=gc());
    return now*f;
}
inline void AddEdge(int u,int v)
{
    to[++Enum]=v, nxt[Enum]=H[u], H[u]=Enum;
    to[++Enum]=u, nxt[Enum]=H[v], H[v]=Enum;
}
void DFS(int x,int f,int ds)
{
    fa[x]=f;
    for(int i=H[x];i;i=nxt[i])
        if(to[i]!=f) DFS(to[i],x,ds+1);
    if(ds>mxdis) mxdis=ds, V=x;
}
void DFS2(int x,int f,bool op)
{
    for(int i=H[x];i;i=nxt[i])
        if(to[i]!=f)
            dis[to[i]][op]=dis[x][op]+1, DFS2(to[i],x,op);
}
void DFS3(int x,int f)
{
    for(int i=H[x];i;i=nxt[i])
        if(to[i]!=f) DFS3(to[i],x);
    if(!Is_d[x])
        if(dis[x][0]>dis[x][1]) res+=dis[x][0],ans[++cnt]=(Triple){U,x,x};
        else res+=dis[x][1],ans[++cnt]=(Triple){V,x,x};
}

int main()
{
    n=read();
    for(int u,v,i=1;i<n;++i) u=read(),v=read(),AddEdge(u,v);
    DFS(1,-1,0);
    U=V, mxdis=0;
    DFS(U,-1,0);
    int x=V,tot=0;
    res=1ll*mxdis*(mxdis+1)>>1;
    while(x!=U) Is_d[x]=1,D[++tot]=x,x=fa[x];
    Is_d[U]=1;
    DFS2(U,-1,0), DFS2(V,-1,1);
    DFS3(U,-1);
    printf("%I64d\n",res);
    for(int i=1;i<=cnt;++i) printf("%d %d %d\n",ans[i].u,ans[i].v,ans[i].w);
    for(int i=1;i<=tot;++i) printf("%d %d %d\n",U,D[i],D[i]);

    return 0;
}

原文地址:https://www.cnblogs.com/SovietPower/p/8426714.html

时间: 2024-08-29 07:59:32

CF.911F.Tree Destruction(构造 贪心)的相关文章

Codeforces 911F Tree Destruction(贪心 &amp;&amp; 树的直径)

题目链接  Tree Destructi 题意  给定一棵树,每次可以选定树上的两个叶子,并删去其中的一个.答案每次加上两个选定的叶子之间的距离. 求最后答案的最大值. 首先求出树的某一条直径,令其端点分别为L, R. 把L看成树的根,那么R一定是叶子结点. 对于那些非直径上的点,离他们最远的点肯定是L或R中的一个(可能也有其他的,但是L或R肯定已经最大了) 所以依次把这些非直径上的点删掉,删掉的时候在L和R中选择一个就行了. 最后把直径删掉即可. 时间复杂度$O(nlogn)$  (应该是可以

CF911F Tree Destruction 解题报告

CF911F Tree Destruction 题意翻译 给你一棵树,每次挑选这棵树的两个叶子,加上他们之间的边数(距离),然后将其中一个点去掉,问你边数(距离)之和最大可以是多少. 输入输出格式 输入格式: The first line contains one integer number n \(n\) ( \(2 \le n \le 2 \times 10^{5}\) ) - the number of vertices in the tree. Next \(n-1\) lines d

HDU 4912 Paths on the tree LCA 排序贪心

lca... 排个序然后暴力保平安 _(:зゝ∠)_ #pragma comment(linker, "/STACK:102400000,102400000") #include"cstdio" #include"iostream" #include"set" #include"queue" #include"string.h" using namespace std; #define

Codeforces 432E Square Tiling(构造+贪心)

我们通常这么写 using (SqlDataReader drm = sqlComm.ExecuteReader()) { drm.Read();//以下把数据库中读出的Image流在图片框中显示出来. MemoryStream ms = new MemoryStream((byte[])drm["Logo"]); Image img = Image.FromStream(ms); this.pictureBox1.Image = img; } 我的写数据 private void b

GCJ 2009 Round2 A 构造贪心策略

题意: 给你一个n?n的元素只为0或1的矩阵,要把该矩阵通过行交换变为上三角矩阵,且交换方式只能为相邻行交换.问最小的交换步数是多少? 思路: 首先这个行的利用价值就是最右边的1位置是多少,直接把行抽象为最右边1的数字即可.注意:这里WA了一发,没有注意数字要初始化为0.无论多么简单,写完之后检查代码且保证逻辑没有一丝错误十分重要! 这个题主要的是构造贪心的法则:题中只需要满足第一行的数字小于1,第二行的数字小于2,-..,第n行的数字小于n.那么就从第一行开始,一行一行的来看,注意若当前行的数

poj 2054 Color a Tree 据说是贪心

Color a Tree Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 7112   Accepted: 2438 Description Bob is very interested in the data structure of a tree. A tree is a directed graph in which a special node is singled out, called the "root&qu

LA 6979 Known Notation 构造+贪心 铜牌题

6979 Known NotationDo you know reverse Polish notation (RPN)? It is a known notation in the area of mathematics andcomputer science. It is also known as postfix notation since every operator in an expression follows allof its operands. Bob is a stude

CF #374 (Div. 2) D. 贪心,优先队列或set

1.CF #374 (Div. 2)   D. Maxim and Array 2.总结:按绝对值最小贪心下去即可 3.题意:对n个数进行+x或-x的k次操作,要使操作之后的n个数乘积最小. (1)优先队列 #include<bits/stdc++.h> #define F(i,a,b) for (int i=a;i<b;i++) #define FF(i,a,b) for (int i=a;i<=b;i++) #define mes(a,b) memset(a,b,sizeof(

CF911F Tree Destruction

题意翻译 给你一棵树,每次挑选这棵树的两个叶子,加上他们之间的边数(距离),然后将其中一个点去掉,问你边数(距离)之和最大可以是多少. 题目描述 You are given an unweighted tree with n n n vertices. Then n−1 n-1 n−1 following operations are applied to the tree. A single operation consists of the following steps: choose t