【bzoj3124】 Sdoi2013—直径
http://www.lydsy.com/JudgeOnline/problem.php?id=3124 (题目链接)
题意
求树的直径以及直径的交。
Solution
我的想法超麻烦,经供参考。。思路还是蛮简单的,就是细节实在是。。。写的我眼泪掉下来。
首先直径很好求,2遍dfs,顺便求出点x儿子节点中的最长链f[x][0],次长链f[x][1]。
考虑如何求直径的交。
对于一条边(u,v),如果它是直径的交,当且仅当所有的直径都经过u,所有的直径都经过v,u的最长链+v的最长链+(u,v)=直径长度。
所以考虑如何求出数组b[x],表示x节点是否被所有直径经过。大家可以自行脑补,我已经不知道自己是怎么AC的了。。
细节
too much。
代码
// bzoj3124
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
#define LL long long
#define inf 2147483640
#define Pi acos(-1.0)
#define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
using namespace std; const int maxn=200010;
struct edge {int to,next,w;}e[maxn<<1];
int head[maxn],son[maxn][2],sum[maxn][2],b[maxn],vis[maxn],cnt,n,tot,rt;
LL f[maxn][3],ans; void link(int u,int v,int w) {
e[++cnt]=(edge){v,head[u],w};head[u]=cnt;
e[++cnt]=(edge){u,head[v],w};head[v]=cnt;
}
void dfs(int x,int fa,LL d) {
if (ans<d) ans=d,rt=x;
for (int i=head[x];i;i=e[i].next) if (e[i].to!=fa) {
dfs(e[i].to,x,d+e[i].w);
if (f[x][0]<f[e[i].to][0]+e[i].w) {
f[x][1]=f[x][0],f[x][0]=f[e[i].to][0]+e[i].w;
son[x][1]=son[x][0],son[x][0]=e[i].to;
sum[x][1]=sum[x][0],sum[x][0]=0;
}
else if (f[x][1]<f[e[i].to][0]+e[i].w) {
son[x][1]=e[i].to;f[x][1]=f[e[i].to][0]+e[i].w;
sum[x][1]=0;
}
if (f[x][0]==f[e[i].to][0]+e[i].w) sum[x][0]++;
if (f[x][1]==f[e[i].to][0]+e[i].w) sum[x][1]++;
}
}
bool Dfs(int x,int fa,LL d) {
f[x][2]=d;
int flag=1,val=b[x],count=0,p;
if (f[x][0]+f[x][1]==ans) flag=0;
val&=flag;
for (int i=head[x];i;i=e[i].next) if (e[i].to!=fa) {
b[e[i].to]=b[x];
if (e[i].to!=son[x][0] && e[i].to!=son[x][1]) b[e[i].to]=val;
else {
if (son[x][0]==e[i].to && sum[x][0]>2) b[e[i].to]=val;
if (son[x][1]==e[i].to && sum[x][1]>1+(f[x][0]==f[x][1])) b[e[i].to]=val;
}
if (f[x][son[x][0]==e[i].to]+f[x][2]==ans) b[e[i].to]=0;
int tmp=Dfs(e[i].to,x,max(f[x][son[x][0]==e[i].to],f[x][2])+e[i].w);
if (!tmp) count++,p=e[i].to;
b[x]&=tmp;flag&=tmp;
}
if (count>1)
for (int i=head[x];i;i=e[i].next) if (e[i].to!=fa && b[e[i].to]) {
b[e[i].to]=0;
Dfs(e[i].to,x,max(f[x][son[x][0]==e[i].to],f[x][2])+e[i].w);
}
if (count==1)
for (int i=head[x];i;i=e[i].next) if (e[i].to!=fa && b[e[i].to] && e[i].to!=p) {
b[e[i].to]=0;
Dfs(e[i].to,x,max(f[x][son[x][0]==e[i].to],f[x][2])+e[i].w);
}
return flag;
}
void dp(int x,int fa) {
for (int i=head[x];i;i=e[i].next) if (e[i].to!=fa) {
dp(e[i].to,x);
if (max(f[x][son[x][0]==e[i].to],f[x][2])+e[i].w+f[e[i].to][0]==ans)
if (b[e[i].to] && b[x])
tot++;
}
}
int main() {
scanf("%d",&n);
for (int u,v,w,i=1;i<n;i++) {
scanf("%d%d%d",&u,&v,&w);
link(u,v,w);
}
dfs(1,0,0);dfs(rt,0,0);
memset(f,0,sizeof(f));
memset(son,0,sizeof(son));
dfs(1,0,0);
printf("%lld\n",ans);
for (int i=1;i<=n;i++) b[i]=1;
Dfs(1,0,0);
dp(1,0);
printf("%d",tot);
return 0;
}
【bzoj3124】 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距离最长链左端点的距离 第二问 ...
- BZOJ3124 SDOI2013直径
本以为必有高论,结果是个思博题.随便找一条直径,最后答案肯定是这条直径上的连续一段,如果某分支长度等于直径上某端的长度这一端都要被剪掉. #include<iostream> #inclu ...
- [bzoj3124] [Sdoi2013]直径
看了child学长的题解才知道怎么写TAT http://www.cnblogs.com/ctlchild/p/5160272.html 以前不知道直径都是过重心的..代码改着改着就和标程完全一样了Q ...
- 2018.11.05 bzoj3124: [Sdoi2013]直径(树形dp)
传送门 一道sbsbsb树形dpdpdp 第一问直接求树的直径. 考虑第二问问的边肯定在同一条直径上均是连续的. 因此我们将直径记下来. 然后对于直径上的每一个点,dpdpdp出以这个点为根的子树中不 ...
- BZOJ3124 [Sdoi2013]直径 【树的直径】
题目 小Q最近学习了一些图论知识.根据课本,有如下定义.树:无回路且连通的无向图,每条边都有正整数的权值来表示其长度.如果一棵树有N个节点,可以证明其有且仅有N-1 条边. 路径:一棵树上,任意两个节 ...
- BZOJ3124: [Sdoi2013]直径 (树形DP)
题意:给一颗树 第一问求直径 第二问求有多少条边是所有直径都含有的 题解:求直径就不说了 解第二问需要自己摸索出一些性质 任意记录一条直径后 跑这条直径的每一个点 如果以这个点不经过直径能到达最远的 ...
- 【BZOJ3124】[Sdoi2013]直径 树形DP(不用结论)
[BZOJ3124][Sdoi2013]直径 Description 小Q最近学习了一些图论知识.根据课本,有如下定义.树:无回路且连通的无向图,每条边都有正整数的权值来表示其长度.如果一棵树有N个节 ...
- [洛谷P3304] [SDOI2013]直径
洛谷题目链接:[SDOI2013]直径 题目描述 小Q最近学习了一些图论知识.根据课本,有如下定义.树:无回路且连通的无向图,每条边都有正整数的权值来表示其长度.如果一棵树有N个节点,可以证明其有且仅 ...
- 3124: [Sdoi2013]直径
3124: [Sdoi2013]直径 https://www.lydsy.com/JudgeOnline/problem.php?id=3124 分析: 所有直径都经过的边,一定都是连续的一段.(画个 ...
随机推荐
- Java中的阻塞队列
1. 什么是阻塞队列? 阻塞队列(BlockingQueue)是一个支持两个附加操作的队列.这两个附加的操作是:在队列为空时,获取元素的线程会等待队列变为非空.当队列满时,存储元素的线程会等待队列可用 ...
- postfix与sendmail冲突
在Linux服务器(CentOS release 6.6)上配置好了sendmail后,测试发送邮件时发现有问题,检查sendmail服务的状态,发现其处于"sendmail dead bu ...
- JAVA Map
基本特性: 维持健值对的集合接口,健不可以重复,每一个健只能映射到一个值. Map替代了原来的虚拟类Directory. Map提供了三种集合视角,keys(KeySet),values(Values ...
- JAVA之直接内存(DirectMemory)
Baisics: JAVA NIO使用,基于通道和缓冲区的IO方式,使用Native函数库直接分配堆外内存(allocateDirect),然后通过一个Java堆中的DirectByteBuffer对 ...
- Ambari server:无法显示内存,CPU等使用率
Ambari server安装完毕后,都能正确显示各种信息.运行了几天后,发现无法显示内存,CPU等信息. 查找日志发现有错误,日志路径:/var/log/ambari-server/ambari-s ...
- OSX下 pip更新及安装python库
直接执行安装命令 $ pip install builtwith 提示pip当前版本为7.1.2,要使用"pip install --upgrade pip"升级到8.1.2 $ ...
- laravel5源码讲解整理
来源:http://yuez.me/laravel-yuan-ma-jie-du/?utm_source=tuicool&utm_medium=referral 目录 入口文件 index.p ...
- FeWeb基础之JavaScript简介
FeWeb基础之JavaScript简介 1.JavaScript的基本介绍 JavaScript是一种基于对象和事件驱动并具有安全性能的脚本语言,它是通过嵌入或调入在标准的HTML语言中实现的.Ja ...
- [WPF系列]基础Combox
示例 参考 WPF combobox SelectedValue binding to string Confused with wpf ComboBox DisplayMemberPath, ...
- 【2016-10-17】【坚持学习】【Day8】【工厂方法模式】
工厂方法模式又叫工厂模式,虚拟构造器模式 定义: 工厂父类负责定义创建产品对象的公共接口,而工厂子类则负责生成具体的产品对象目的是将产品类的实例化操作延迟到工厂子类中完成,即通过工厂子类来确定究竟应该 ...