[SDOI2013] 直径
传送门:>HERE<
题意:给出一颗树,求出被所有的直径都经过的边的数量
解题思路:
先求出任意一条直径并记录节点。
然后依次枚举直径上的每一个节点,判断从当前节点延伸出去的非直径的一条路径的最大值,如果这一条链的长度与它所分割出来的直径的两半中的任何一半的长度相等,则即为分叉。分叉的部分由于都是直径,必然不是每条直径都会经过的,所以这两段内的边一定不会属于答案。更新一下边界就可以了。由于直径上的点每个只被访问了一遍,并且延伸出去的也最多只被访问一次(想一想,为什么),所以均摊O(n)
Code
注意,不能向我一样在扫的时候还O(n)求一遍最大值,这样复杂度就是接近O(n^2)了。在dfs的过程打擂就好了
/*by DennyQi*/
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>
#define r read()
#define Max(a,b) (((a)>(b))?(a):(b))
#define Min(a,b) (((a)<(b))?(a):(b))
using namespace std;
typedef long long ll;
#define int long long
const int MAXN = ;
const int INF = 0x3f3f3f3f;
const int MOD = ;
inline int read(){
int x = ; int w = ; register unsigned char c = getchar();
for(; c^'-' && (c < '' || c > ''); c = getchar());
if(c == '-') w = -, c = getchar();
for(; c >= '' && c <= ''; c = getchar()) x = (x<<) + (x<<) + c - '';
return x * w;
}
int N,a,b,c,P,Q,_max,L,R,flg;
int first[MAXN*],next[MAXN*],to[MAXN*],cost[MAXN*],num_edge;
int d[MAXN],pre[MAXN],wei[MAXN],vis[MAXN],rad[MAXN],Dist[MAXN];
queue <int> q;
inline void add(int u, int v, int w){
to[++num_edge] = v;
cost[num_edge] = w;
next[num_edge] = first[u];
first[u] = num_edge;
}
inline void BFS(int s){
memset(d,0x3f,sizeof(d));
d[s] = ;
q.push(s);
vis[s] = ;
int u,v;
while(!q.empty()){
u = q.front();q.pop();
for(int i = first[u]; i; i = next[i]){
v = to[i];
if(!vis[v]){
d[v] = d[u] + cost[i];
vis[v] = ;
q.push(v);
pre[v] = u;
wei[v] = cost[i];
}
}
}
}
void DFS(int x, int fa, int tot){
_max = Max(_max, tot);
int v;
for(int i = first[x]; i != ; i = next[i]){
v = to[i];
if((v != fa) && (!rad[v])){
flg = ;
DFS(v, x, tot + cost[i]);
}
}
}
main(){
N=r;
for(int i = ; i < N; ++i){
a=r,b=r,c=r;
add(a,b,c),add(b,a,c);
}
BFS();
for(int i = ; i <= N; ++i) if(d[i] > _max) _max = d[i],P = i;
memset(vis,,sizeof(vis));
BFS(P);
_max = ;
for(int i = ; i <= N; ++i) if(d[i] > _max) _max = d[i], Q = i;
printf("%lld\n", d[Q]);
int x=P,y=Q;
while(y != x) rad[y] = , y = pre[y];
rad[P] = , rad[Q] = ;
x=P,y=Q;
int dis = d[Q];
L = Q, R = P;
while(y != x){
flg = ;
_max = -;
DFS(y, , );
if(!flg) _max = -;
if(_max != -){
if(_max == dis){ R = y; break; }
if(_max == d[Q] - dis) L = y;
}
dis -= wei[y];
y = pre[y];
}
y = L;
int ans = ;
while(y != R) ++ans, y = pre[y];
printf("%lld", ans);
return ;
}
[SDOI2013] 直径的更多相关文章
- bzoj3124: [Sdoi2013]直径 树形dp two points
题目链接 bzoj3124: [Sdoi2013]直径 题解 发现所有直径都经过的边 一定在一条直径上,并且是连续的 在一条直径上找这段区间的两个就好了 代码 #include<map> ...
- bzoj千题计划134:bzoj3124: [Sdoi2013]直径
http://www.lydsy.com/JudgeOnline/problem.php?id=3124 第一问: dfs1.dfs2 dfs2中记录dis[i]表示点i距离最长链左端点的距离 第二问 ...
- [洛谷P3304] [SDOI2013]直径
洛谷题目链接:[SDOI2013]直径 题目描述 小Q最近学习了一些图论知识.根据课本,有如下定义.树:无回路且连通的无向图,每条边都有正整数的权值来表示其长度.如果一棵树有N个节点,可以证明其有且仅 ...
- 3124: [Sdoi2013]直径
3124: [Sdoi2013]直径 https://www.lydsy.com/JudgeOnline/problem.php?id=3124 分析: 所有直径都经过的边,一定都是连续的一段.(画个 ...
- 【BZOJ3124】[Sdoi2013]直径 树形DP(不用结论)
[BZOJ3124][Sdoi2013]直径 Description 小Q最近学习了一些图论知识.根据课本,有如下定义.树:无回路且连通的无向图,每条边都有正整数的权值来表示其长度.如果一棵树有N个节 ...
- BZOJ_3124_[Sdoi2013]直径_树形DP
BZOJ_3124_[Sdoi2013]直径_树形DP Description 小Q最近学习了一些图论知识.根据课本,有如下定义.树:无回路且连通的无向图,每条边都有正整数的权值来表示其长度.如果一棵 ...
- Bzoj 3124: [Sdoi2013]直径 题解
3124: [Sdoi2013]直径 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 1222 Solved: 580[Submit][Status] ...
- 【bzoj3124】 Sdoi2013—直径
http://www.lydsy.com/JudgeOnline/problem.php?id=3124 (题目链接) 题意 求树的直径以及直径的交. Solution 我的想法超麻烦,经供参考..思 ...
- bzoj 3124: [Sdoi2013]直径
#include<cstdio> #include<iostream> #define M 400009 #define ll long long using namespac ...
- bzoj 3124 [Sdoi2013]直径(dfs)
Description 小Q最近学习了一些图论知识.根据课本,有如下定义.树:无回路且连通的无向图,每条边都有正整数的权值来表示其长度.如果一棵树有N个节点,可以证明其有且仅有N-1 条边. 路径:一 ...
随机推荐
- .net Core 调用微信Jsapi接口,H5解析二维码
项目里需要用到扫描二维码,自己实现,不会. 找到了两种解决方案: 通过reqrcode.js,这是一个前端解析二维码内容的js库.如果二维码比较清晰,用这种效果也不错 调用微信扫一扫功能,这种效果很好 ...
- Python_每日习题_0006_斐波那契数列
程序设计: 斐波那契数列(Fibonacci sequence),从1,1开始,后面的每一项等于前面两项之和. 图方便就递归实现,图性能就用循环. # for 循环 target = int(inpu ...
- 出题人的RP值(牛客练习赛38--A题)(排序)
链接:https://ac.nowcoder.com/acm/contest/358/A来源:牛客网 题目描述 众所周知,每个人都有自己的rp值(是个非负实数),膜别人可以从别人身上吸取rp值. 然而 ...
- IOS-43-导航栏标题navigationItem.title不能改变颜色的两种解决方法
IOS-43-导航栏标题navigationItem.title不能改变颜色的两种解决方法 IOS-43-导航栏标题navigationItem.title不能改变颜色的两种解决方法 两种方法只是形式 ...
- 第一部分之简单字符串SDS(第二章)
一,什么是SDS? 1.引出SDSC字符串:c语言中,用空字符结尾的字符数组表示字符串简单动态字符串(SDS):Redis中,用SDS来表示字符串.在Redis中,包含字符串值的键值对在底层都是由SD ...
- shell脚本--php执行普通shell命令
这里只演示一些普通的shell命令,一些需要root用户权限执行的命令,请参考:php以root权限执行shell命令 php执行shell命令,可以使用下面几个函数: string system ( ...
- 转:Linux下查看tomcat占用端口
https://blog.csdn.net/liufuwu1/article/details/71123597[root@server-crm mysql]# ps -ef | grep " ...
- 生成短链接的URL
假设你想做一个像微博短链接那样的短链接服务,短链接服务生成的URL都非常短例如: http://t.cn/E70Piib, 我们应该都能想到链接中的E70Piib对应的就是存储长链接地址的数据记录的I ...
- Windows Docker 安装
win7.win8 .win10等需要利用 docker toolbox 来安装,国内可以使用阿里云的镜像来下载,下载地址:http://mirrors.aliyun.com/docker-toolb ...
- java Date时间的各种转换方式和Mysql存时间类型字段的分析
一:各种Date之间的转换方法 public class TimeTest { public static void main(String[] args) { Date date = new Dat ...