【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 分析: 所有直径都经过的边,一定都是连续的一段.(画个 ...
随机推荐
- CocoaPods安装及使用详情
CocoaPods是什么? 当你开发iOS应用时,会经常使用到很多第三方开源类库,比如JSONKit,SDWebImage等等.可能某个类库又用到其他类库,所以要使用它,必须得另外下载其他类库,而其他 ...
- 敏捷开发与jira
项目背景 项目是基于一套公司自主研发的平台做企业信息化的项目管理业务,经过两个里程碑的交付,已经在客户现场使用,每次版本都能按期交付,延迟较少,客户满意度也高. 项目开发过程采用的敏捷的方法,用类Sc ...
- 关于UIApplication单例传值
由于UIApplication的是一个系统级别的单例,那么就能够省去自己创建单例的方法,将需要需要的类对象,在UIApplication单例内声明一个,通过点语法来实现单个 需要调用的实现单例模式的类 ...
- ORACLE 12C新特性——CDB与PDB
Oracle 12C引入了CDB与PDB的新特性,在ORACLE 12C数据库引入的多租用户环境(Multitenant Environment)中,允许一个数据库容器(CDB)承载多个可插拔数据库( ...
- Linux如何查看JDK的安装路径
如何在一台Linux服务器上查找JDK的安装路径呢? 有那些方法可以查找定位JDK的安装路径?是否有一些局限性呢? 下面总结了一下如何查找JDK安装路径的方法. 1:echo $JAVA_HOME ...
- Java之TreeMap
基本特性: 基于红黑树. 非线程安全. 同步使用: SortedMap m = Collections.synchronizedSortedMap(new TreeMap(...))
- 【转】Flex 布局语法教程
网页布局(layout)是CSS的一个重点应用. 布局的传统解决方案,基于盒状模型,依赖 display属性 + position属性 + float属性.它对于那些特殊布局非常不方便,比如,垂直居中 ...
- [Java入门笔记] 面向对象三大特征之:继承
理解什么是继承 首先我们知道,面对对象有三大特征: 封装:解决了数据的安全性问题 继承:解决了代码的重用问题 多态:解决了程序的扩展问题 上一篇博客中,我们了解了一下封装,现在我了再来看看什么是继承. ...
- J2EE基础之Servlet
J2EE基础之Servlet 1. 什么是Servlet? Servlet即Java服务小程序,是使用应用程序设计接口以及相关类和方法的Java程序.它可以作为一种插件,像Applet程序一样嵌入到 ...
- 敏捷BI比传统BI功能强大是否属实?
关于大数据的资讯铺天盖地而来,让人眼花缭乱.虽然资讯很精彩,我们也看到了大数据背后的价值,很多企业选择了商业智能BI产品.商业智能在使用上可分为敏捷BI与传统BI,从名字来看敏捷BI要比传统BI显得利 ...