【洛谷 P3304】[SDOI2013]直径(树的直径)
题目链接
题意,求一棵树被所有直径经过的边的条数。
这题是我们8.25KS图论的最后一题,当时我果断打了暴力求所有直径然后树上差分统计的方法,好像有点小问题,boom0了。
考完改这题,改了好久,各种各样的小bug,至少有七八个。。。
思路:先随便找一条直径,然后从一个端点开始遍历这条直径,如果当前点能分叉出一条直径,那么这条直径后面的点都不可能被所有直径穿过了,于是我们找到第一个能分叉的点,然后再从这个点往回遍历,找到第一个能分叉的点,这2个点中间的路径的边即为所求。
代码就算了吧,打这题时我就没想过要有可读性
#include <cstdio>
#include <algorithm>
#include <queue>
using namespace std;
#define INF 2147483647
#define Open(s) freopen(s".in","r",stdin);freopen(s".out","w",stdout);
#define Close fclose(stdin); fclose(stdout);
const int MAXN = 200010;
inline int read(){
int s = 0, w = 1;
char ch = getchar();
while(ch < '0' || ch > '9') { if(ch == '-') w = -1; ch = getchar(); }
while(ch >= '0' && ch <= '9') { s = s * 10 + ch - '0'; ch = getchar(); }
return s * w;
}
struct Edge{
int next, to, dis;
}e[MAXN << 1];
int num, head[MAXN], flag[MAXN];
inline void Add(int from, int to, int dis){
e[++num] = (Edge){ head[from], to, dis };
head[from] = num;
}
int pre[MAXN], in[MAXN];
int n, ans, Maxu, ans1;
long long Max;
void dfs(int u, int fa, long long dep){
if(dep > Max) Max = dep, Maxu = u;
for(int i = head[u]; i; i = e[i].next)
if(e[i].to != fa)
dfs(e[i].to, u, dep + e[i].dis);
}
void DFS(int u, int fa, long long dep){
pre[u] = fa;
if(dep > Max) Max = dep, Maxu = u;
for(int i = head[u]; i; i = e[i].next)
if(e[i].to != fa)
DFS(e[i].to, u, dep + e[i].dis);
}
bool existOther(int u, int fa, long long dep){
if(dep == Max) return true;
for(int i = head[u]; i; i = e[i].next)
if(e[i].to != fa)
if(existOther(e[i].to, u, dep + e[i].dis)) return true;
return false;
}
int A, B, C;
int main(){
Open("diameter");
n = read();
for(int i = 1; i < n; ++i){
A = read(); B = read(); C = read();
Add(A, B, C); Add(B, A, C);
}
Max = -1; dfs(1, 0, 0);
Max = -1; DFS(Maxu, 0, 0);
int now = Maxu, o = 0, fa = 0, Plus = 0;
long long deep = 0;
while(now) flag[now] = 1, now = pre[now];
for(int i = 1; i <= n; ++i) if(!flag[i]) pre[i] = 0;
now = Maxu;
while(now){
Plus = 0;
for(int i = head[now]; i; i = e[i].next)
if(e[i].to != pre[now] && e[i].to != fa){
if(existOther(e[i].to, now, deep + e[i].dis)){
o = now;
break;
}
}
else if(e[i].to == pre[now]) Plus = e[i].dis;
if(!o && !pre[now]) o = now;
if(o) break;
fa = now;
now = pre[now];
deep += Plus;
} //找到第一个分叉的点
ans = 0; //往回遍历
now = o;
fa = pre[now];
deep = Max - deep;
while(now != Maxu){
int nxt;
++ans;
for(int i = head[now]; i; i = e[i].next)
if(pre[e[i].to] != now && e[i].to != fa){
if(existOther(e[i].to, now, deep + e[i].dis)){
printf("%I64d\n%d\n", Max, ans - 1);
//system("pause");
return 0;
}
}
else if(pre[e[i].to] == now) nxt = e[i].to, Plus = e[i].dis;
fa = now;
now = nxt;
deep += Plus;
}
printf("%I64d\n%d\n", Max, ans); //如果都不能分叉
Close;
//system("pause");
return 0;
}
【洛谷 P3304】[SDOI2013]直径(树的直径)的更多相关文章
- [洛谷P3304] [SDOI2013]直径
洛谷题目链接:[SDOI2013]直径 题目描述 小Q最近学习了一些图论知识.根据课本,有如下定义.树:无回路且连通的无向图,每条边都有正整数的权值来表示其长度.如果一棵树有N个节点,可以证明其有且仅 ...
- 洛谷P3373 [模板]线段树 2(区间增减.乘 区间求和)
To 洛谷.3373 [模板]线段树2 题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数加上x 2.将某区间每一个数乘上x 3.求出某区间每一个数的和 输入输出格式 输入格 ...
- 【BZOJ2830/洛谷3830】随机树(动态规划)
[BZOJ2830/洛谷3830]随机树(动态规划) 题面 洛谷 题解 先考虑第一问. 第一问的答案显然就是所有情况下所有点的深度的平均数. 考虑新加入的两个点,一定会删去某个叶子,然后新加入两个深度 ...
- Bzoj3197/洛谷3296 [SDOI2013]刺客信条assassin(树的重心+树Hash+树形DP+KM)
题面 Bzoj 洛谷 题解 (除了代码均摘自喻队的博客,可是他退役了) 首先固定一棵树,枚举另一棵树,显然另一棵树只有与这棵树同构才有可能产生贡献 如果固定的树以重心为根,那么另一棵树最多就只有重心为 ...
- 洛谷P3655 差分数组 树状数组
题目链接:https://www.luogu.org/problemnew/show/P3655 不一定对,仅供参考,不喜勿喷,不喜勿喷. 先copy洛谷P3368 [模板]树状数组 2 题解里面一位 ...
- 洛谷P4332 [SHOI2014]三叉神经树(LCT,树剖,二分查找,拓扑排序)
洛谷题目传送门 你谷无题解于是来补一发 随便百度题解,发现了不少诸如树剖\(log^3\)LCT\(log^2\)的可怕描述...... 于是来想想怎么利用题目的性质,把复杂度降下来. 首先,每个点的 ...
- BZOJ2243 洛谷2486 [SDOI2011]染色 树链剖分
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ2243 题目传送门 - 洛谷2486 题意概括 一棵树,共n个节点. 让你支持以下两种操作,共m次操 ...
- 洛谷:P1087 FBI树 P1030 求先序排列 P1305 新二叉树
至于为啥把这三个题放到一起,大概是因为洛谷的试炼场吧,三道树的水题,首先要理解 先序中序后序遍历方法. fbi树由于数量小,在递归每个区间时,暴力跑一遍区间里的数,看看是否有0和1.至于递归的方法,二 ...
- 洛谷P3459 [POI2007]MEG-Megalopolis [树链剖分]
题目传送门 MEG 题目描述 Byteotia has been eventually touched by globalisation, and so has Byteasar the Postma ...
- POJ 1985.Cow Marathon-树的直径-树的直径模板(BFS、DFS(vector存图)、DFS(前向星存图))
Cow Marathon Time Limit: 2000MS Memory Limit: 30000K Total Submissions: 7536 Accepted: 3559 Case ...
随机推荐
- Django 2.0官方文档中文 渣翻 总索引(个人学习,欢迎指正)
Django 2.0官方文档中文 渣翻 总索引(个人学习,欢迎指正) 置顶 2017年12月08日 11:19:11 阅读数:20277 官方原文: https://docs.djangoprojec ...
- jmeter使用beanshell构造参数化
1.先在本地写一个java类,用来随机生成一个数字,如: package com.jmeter.test; public class BeanShellTest { public int getRan ...
- Selenium页面工厂+数据驱动测试框架
工程的目录结构: pom.xml文件: <?xml version="1.0" encoding="UTF-8"?><project xmln ...
- MySQL☞length函数
length(字符串/列名):求出该字符串/列名中字符的个数 格式: select length(列名) from 表名 如下图:
- CentOS Linux release 7.5.1804下安装MySQL5.7.24
1.环境查看: 2.卸载自带MariaDB数据库: 3.下载MySQL5.7.14安装包: 4.使用wget工具下载需要安装数据库的依赖包: 5.解压缩bundel包: 6.按照顺序进行安装: 7.数 ...
- java计算两个日期之间的相隔天数
[原创] 之前在很多竞赛的题目中有这样饿一类题,计算给定两个日期之间的相隔天数,或者很多类似的题目,都是需要转化到这个问题上时,之前用c++写的时候思想是这样的,一个结构体,包括年月日,还有一个计算下 ...
- [转] const int *a与int *const a,const int *const a的区别
http://blog.csdn.net/zhangheng837964767/article/details/33783511 关键问题点:const 属于修饰符 ,关键是看const 修饰的位置在 ...
- 关于如何利用原生js动态给一个空对象添加属性以及属性值
首先,回忆一下,访问对象属性一共有两种方法:点获取法和方括号获取法.而我们最常用的就是点获取法了.但是当我们遇到需要给对象动态添加属性和属性值时,点获取法好像就不太好用了,尤其是我们不知道属性名的时候 ...
- Java基础知识-去重
java基础知识-去掉list集合中的重复元素: 思路: 首先新建一个容器resultList用来存放去重之后的元素 然后遍历sourceList集合中的元素 判断所遍历的元素是否已经存在于resul ...
- arcgis的炸开多边形功能
有时候我们使用dissolve工具,或其他操作会将空间不相连的多边形对应的属性合并到一起,如图: 在高级编辑工具中: 有这样一个工具,但是它能满足我的要求,但是他不是批量的,不过它使用起来比较方便. ...