Gym - 100781A Adjoin the Networks (树的直径)
题意:
n个点,m条边,m <= n <= 100000,边的长度都为1。
点从 0 ~ n-1 编号。开始时图是不连通的,并且没有环。
通过加入一些边后,可以使图连通。要求加入的边不能多余(即生成的图是一棵树)。
问连通后的图,任意两点之间的距离的最大值,最小可以是多少?
既然刚开始图不连通也无环,那么就是一些树(特殊情况是点)。
于是题目就变成了,如何把很多棵树连起来,使最后生成的树直径最小。
可以想到,如果把两棵直径为 a 和 b 的树加一条边连成一棵,那么直径最小的新树直径为 (a+1)/2 + (b+1)/2 + 1 (两棵树的直径 / 2,向上取整,的和再加 1)
选择其中一个直径最大的子树,遍历所有其他的子树,然后将其他的子树加到这个子树上面。
求树的直径可以用DP。
这道题场上很快想出来了做法。然后一直T在 test 22。
原因是不会写树的直径DP求法,以及,memset超时。
每次找到新的联通块(新的一棵树)求树的直径就要memset一遍是不需要的。因为那些点肯定是不冲突的。
#include <cstdio> #include <cstring> #include <algorithm> #include <iostream> #include <queue> #include <cmath> #include <stack> #include <set> #include <map>using namespace std; const int maxn = 200000 + 1000;int fa[maxn], dis[maxn], tot = 0, v[maxn]; bool vis[maxn];struct Node {int v, next, last, z; }a[maxn];void build(int x, int y) {tot++;a[tot].v = y;a[tot].next = a[x].last;a[x].last = tot; }void dp(int x, int &ans) {v[x] = 1;for (int tmp = a[x].last; tmp; tmp = a[tmp].next){int y = a[tmp].v;if (v[y]) continue;dp(y, ans);ans = max(ans, dis[x] + dis[y] + 1);dis[x] = max(dis[x], dis[y] + 1);} }void DFS(int x) {vis[x] = true;for (int tmp = a[x].last; tmp; tmp = a[tmp].next){int y = a[tmp].v;if (!vis[y]) DFS(y);} }int main() {int n, m;scanf("%d%d", &n, &m);int x, y;for (int i = 1; i <= m; i++){scanf("%d%d", &x, &y);build(x, y);build(y, x);}memset(vis, false, sizeof(vis));memset(v, 0, sizeof(v));memset(dis, 0, sizeof(dis));int q[maxn], tt = 0;for (int i = 0; i < n; i++)if (!vis[i]){int t = 0;dp(i, t);q[++tt] = t;DFS(i);}int ans = 0, flag = 0;for (int i = 1; i <= tt; i++)if (q[i] > ans){ans = q[i];flag = i;}for (int i = 1; i <= tt; i++)if (i != flag)ans = max(ans, (q[i]+1)/2+(ans+1)/2 + 1);printf("%d\n", ans);return 0; }
转载于:https://www.cnblogs.com/ruthank/p/9379848.html
Gym - 100781A Adjoin the Networks (树的直径)相关推荐
- [51nod] 1766树上的最远点对 树的直径 树剖LCA+ST表静态查询
题意: 给你一棵带权树,q次查询,每次给出两个区间,[l1,r1][l2,r2][l_1,r_1] [l_2,r_2][l1,r1][l2,r2]从这两个区间中分别选择两个数字,使得这两个点的 ...
- 小A与欧拉路(牛客-树的直径)
题解: 欧拉路:从图中任意一个点开始到图中任意一个点结束的路径,并且图中每条边只通过恰好一次 问你走完这树上所有的点最短路径是什么. 因为树是没有环的,所以你走到叶子结点的时候需要往回走,也就是再走一 ...
- luogu P4408 [NOI2003]逃学的小孩(树的直径)
整理的算法模板合集: ACM模板 看了半天的题原来没有告诉你三个点的坐标,不然直接跑最短路即可.要求最长的时间,所以我们要自己找到三个点,而在树中最长的路径也就是树的直径.那么本题就可以简化为:在一棵 ...
- 模板 - 树上问题(树的直径、动态查询树的直径、树的重心)
整理的算法模板合集: ACM模板 目录 一.树的直径 树形DP 两次DFS / BFS(找到直径的两个端点) 二.动态修改树的边权并求每个时刻的直径(线段树) 三.树的重心 一.树的直径 树的直径满足 ...
- 【树的直径】解题报告: luogu P3629 [APIO2010]巡逻(树的直径,位运算成对变换,思维)
题目链接:P3629 [APIO2010]巡逻 首先看题,从1号结点开始,全部遍历并回到1号结点会恰好经过所有的边两次,这样总长度为 2∗(n−1)2*(n-1)2∗(n−1). 那么如果建立一条路以 ...
- 0x63.图论 - 树的直径与最近公共祖先
目录 一.树的直径(Diameter) 1.树形DP求树的直径 2.两次BFS/DFS求树的直径 1.POJ 1985.Cow Marathon(DFS求树的直径模板题) 2.AcWing 350. ...
- [Bzoj2282]消防(二分答案+树的直径)
Description 某个国家有n个城市,这n个城市中任意两个都连通且有唯一一条路径,每条连通两个城市的道路的长度为zi(zi<=1000). 这个国家的人对火焰有超越宇宙的热情,所以这个国家 ...
- 树的直径【p3629】[APIO2010]巡逻
Description 在一个地区中有 n 个村庄,编号为 1, 2, ..., n.有 n – 1 条道路连接着这些村 庄,每条道路刚好连接两个村庄,从任何一个村庄,都可以通过这些道路到达其 他任一 ...
- Codeforces 337D Book of Evil:树的直径【结论】
题目链接:http://codeforces.com/problemset/problem/337/D 题意: 给你一棵树,n个节点. 如果一个节点处放着"罪恶之书",那么它会影响 ...
- CodeForces-734E Anton and Tree 树的直径
题目大意: 给定一棵有n个节点的树,有黑点白点两种节点. 每一次操作可以选择一个同种颜色的联通块将其染成同一种颜色 现在给定一个初始局面问最少多少步可以让树变为纯色. 题解: 首先我们拿到这棵树时先将 ...
最新文章
- 新手也能立即上手,用Python90多行代码画出“樱花园”仙境(源码+注释)
- HDU_1253 胜利大逃亡(BFS)
- getcwd()函数用法
- scalac和classpath的设置
- 下载python流程-Python编写win程序的操作流程
- phpstudy连接SQL Server 2008数据库 以及 php使用sql server出现乱码解决方式
- JavaSE基础篇之-Java 流(Stream)、文件(File)和IO
- linux怎么查看hwaddr_怎么查询linux centos mac地址
- 如何用教科书式的方法,着手分析一个行业?
- 用java画企鹅_Fireworks绘制简笔QQ企鹅图像
- 学校建立学生心理健康的必要性
- 使用 Lightly 在线格式化 HTML
- 如何编写Junit测试代码
- Linux CentOS 中安装 MySQL 与卸载 MySQL(三)
- 磁盘划分和磁盘格式化
- 全球主要大数据公司盘点
- 原生微信小程序项目基础框架搭建
- 程序员的 MySQL 面试金典
- 疯群系统独立3.1.2版本微信社群人脉系统社群空间站PHP源码
- 如何在Photoshop中使用剪贴蒙版(而非图层蒙版)