Codeforces 911F Tree Destruction(贪心 && 树的直径)
题目链接 Tree Destructi
题意 给定一棵树,每次可以选定树上的两个叶子,并删去其中的一个。答案每次加上两个选定的叶子之间的距离。
求最后答案的最大值。
首先求出树的某一条直径,令其端点分别为L, R。
把L看成树的根,那么R一定是叶子结点。
对于那些非直径上的点,离他们最远的点肯定是L或R中的一个(可能也有其他的,但是L或R肯定已经最大了)
所以依次把这些非直径上的点删掉,删掉的时候在L和R中选择一个就行了。
最后把直径删掉即可。
时间复杂度$O(nlogn)$ (应该是可以做到$O(n)$的,但是我比较懒)
#include <bits/stdc++.h> using namespace std; #define rep(i, a, b) for (int i(a); i <= (b); ++i)
#define dec(i, a, b) for (int i(a); i >= (b); --i) typedef long long LL; const int N = 2e5 + 10; vector <int> v[N]; int n;
int cnt;
int x, y;
int L, R; int f[N][20];
int a[N];
int deep[N], father[N];
int Father[N];
int vis[N];
int c[N];
int isroot[N]; LL ans = 0; queue <int> q; void dfs(int x, int fa, int now){
deep[x] = now;
if (fa){
f[x][0] = fa;
for (int i = 0; f[f[x][i]][i]; ++i)
f[x][i + 1] = f[f[x][i]][i];
} if (now > cnt) cnt = now, L = x;
for (auto u : v[x]){
if (u == fa) continue;
dfs(u, x, now + 1);
}
} void dfs2(int x, int fa, int now){
father[x] = fa;
if (now > cnt) cnt = now, R = x;
for (auto u : v[x]){
if (u == fa) continue;
dfs2(u, x, now + 1);
}
} int LCA(int a, int b){
if (deep[a] < deep[b]) swap(a, b);
for (int i = 0, delta = deep[a] - deep[b]; delta; delta >>= 1, ++i)
if (delta & 1) a = f[a][i]; if (a == b) return a;
dec(i, 19, 0) if (f[a][i] != f[b][i]){
a = f[a][i];
b = f[b][i];
} return f[a][0];
} int dis(int x, int y){
int z = LCA(x, y);
return deep[x] + deep[y] - 2 * deep[z];
} void dfs3(int x, int fa){
vis[x] = 1;
Father[x] = fa;
for (auto u : v[x]){
if (vis[u]) continue;
dfs3(u, x);
++c[x];
}
} int main(){ scanf("%d", &n);
rep(i, 1, n){
scanf("%d%d", &x, &y);
v[x].push_back(y);
v[y].push_back(x);
} L = 0, cnt = 0;
dfs(1, 0, 0); cnt = 0;
R = 0;
memset(father, 0, sizeof father);
dfs2(L, 0, 0); cnt = 0;
x = R;
while (x){
++cnt;
a[cnt] = x;
x = father[x];
} memset(vis, 0, sizeof vis);
rep(i, 1, cnt) vis[a[i]] = 1;
rep(i, 1, n) isroot[i] = vis[i];
rep(i, 1, n) if (!vis[i]){
int now = max(dis(i, L), dis(i, R));
ans += 1ll * now;
} memset(c, 0, sizeof c);
rep(i, 1, cnt) dfs3(a[i], 0);
rep(i, 1, n) if (c[i] == 0 && !isroot[i]) q.push(i); ans = ans + 1ll * cnt * (cnt - 1) / 2;
printf("%lld\n", ans); while (!q.empty()){
x = q.front(); q.pop();
vis[x] = 1;
int al = dis(x, L), ar = dis(x, R);
if (al > ar) printf("%d %d %d\n", L, x, x);
else printf("%d %d %d\n", R, x, x); int u = Father[x];
--c[u];
if (c[u] == 0 && !isroot[u]) q.push(u);
} rep(i, 1, cnt - 1) printf("%d %d %d\n", a[i], a[cnt], a[i]);
return 0;
}
Codeforces 911F Tree Destruction(贪心 && 树的直径)的更多相关文章
- Codeforces.911F.Tree Destruction(构造 贪心)
题目链接 \(Description\) 一棵n个点的树,每次可以选择树上两个叶子节点并删去一个,得到的价值为两点间的距离 删n-1次,问如何能使最后得到的价值最大,并输出方案 \(Solution\ ...
- Codeforces 911F Tree Destruction
Tree Destruction 先把直径扣出来, 然后每个点都和直径的其中一端组合, 这样可以保证是最优的. #include<bits/stdc++.h> #define LL lon ...
- [Codeforces 911F] Tree Destruction 解题报告(贪心)
题目链接: http://codeforces.com/contest/911/problem/F 题目大意: 给你一棵树,每次挑选这棵树的两个度数为1的点,加上他们之间的边数(距离),然后将其中一个 ...
- Codeforces 734E Anton and Tree(缩点+树的直径)
题目链接: Anton and Tree 题意:给出一棵树由0和1构成,一次操作可以将树上一块相同的数字转换为另一个(0->1 , 1->0),求最少几次操作可以把这棵数转化为只有一个数字 ...
- Farthest Nodes in a Tree ---LightOj1094(树的直径)
题目链接:http://lightoj.com/volume_showproblem.php?problem=1094 Given a tree (a connected graph with no ...
- [NOI2003]逃学的小孩 (贪心+树的直径+暴力枚举)
Input 第一行是两个整数N(3 <= N <= 200000)和M,分别表示居住点总数和街道总数.以下M行,每行给出一条街道的信息.第i+1行包含整数Ui.Vi.Ti(1<=Ui ...
- codeforces 14D(搜索+求树的直径模板)
D. Two Paths time limit per test 2 seconds memory limit per test 64 megabytes input standard input o ...
- Codeforces Round #379 (Div. 2) E. Anton and Tree 缩点 树的直径
传送门 题意: 这道题说的是在一颗有两种颜色的树上,每操作一个节点,可以改变这个节点颜色和相邻同色节点的颜色.问最少操作次数,使得树上颜色相同. 思路: 先缩点,把相同的颜色的相邻节点缩在一起.再求出 ...
- codeforces#1187E. Tree Painting(树换根)
题目链接: http://codeforces.com/contest/1187/problem/E 题意: 给出一颗树,找到一个根节点,使所有节点的子节点数之和最大 数据范围: $2 \le n \ ...
随机推荐
- Linux命令之---find
命令简介 find明林用于查找目录下的文件,同时也可以调用其他命令执行相应的操作 命令格式 find pathname -options [-print -exec -ok ...] find [选项 ...
- 笔记-编程-IO模型
笔记-编程-IO模型 1. 简介 常用IO模型 1) 同步阻塞IO(Blocking IO) 2) 同步非阻塞IO(Non-blocking IO) 3) IO ...
- kafka 的offset的重置
最近在spark读取kafka消息时,每次读取都会从kafka最新的offset读取.但是如果数据丢失,如果在使用Kafka来分发消息,在数据处理的过程中可能会出现处理程序出异常或者是其它的错误,会造 ...
- Android四大组件之服务
创建一个服务,并与活动绑定 作为安卓四大组件之一的服务,毫无例外也要在manifast中进行注册 新建服务类继承于Service,并覆盖onBind( )方法,用于与活动绑定 public class ...
- HDU 4825 Xor Sum (trie树处理异或)
Xor Sum Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 132768/132768 K (Java/Others)Total S ...
- 【IPv6】ISATAP隧道技术详解
一.基本概念 ISATAP(Intra-SiteAutomatic Tunnel Addressing Protocol) ISATAP是一种非常容易部署和使用的IPv6过渡机制.在 ...
- MySQL主从复制入门
1.MySQL主从复制入门 首先,我们看一个图: MySQL 主从复制与读写分离概念及架构分析 影响MySQL-A数据库的操作,在数据库执行后,都会写入本地的日志系统A中. 假设,实时的将变化了的日志 ...
- ORA-01017: invalid username/password; logon denied异常的分析
今天在整合SpringMVC与mybatis的时候遇到了一个异常: 四月 24, 2017 10:37:31 下午 org.apache.catalina.core.StandardWrapperVa ...
- 用Vundle管理Vim插件
作为程序员,一个好用的Vim,是极其重要的,而插件能够使原本功能羸弱的Vim变得像其他功能强大的IDE一样好用.然而下载.配置插件的过程比较繁琐,大家往往需要自己进行下载/配置等操作,如果还涉及到更新 ...
- codevs 1081 线段树练习 2 区间更新 单点查询 无lazy
题目描述 Description 给你N个数,有两种操作 1:给区间[a,b]的所有数都增加X 2:询问第i个数是什么? 输入描述 Input Description 第一行一个正整数n,接下来n行n ...