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—直径的更多相关文章

  1. bzoj3124: [Sdoi2013]直径 树形dp two points

    题目链接 bzoj3124: [Sdoi2013]直径 题解 发现所有直径都经过的边 一定在一条直径上,并且是连续的 在一条直径上找这段区间的两个就好了 代码 #include<map> ...

  2. bzoj千题计划134:bzoj3124: [Sdoi2013]直径

    http://www.lydsy.com/JudgeOnline/problem.php?id=3124 第一问: dfs1.dfs2 dfs2中记录dis[i]表示点i距离最长链左端点的距离 第二问 ...

  3. BZOJ3124 SDOI2013直径

    本以为必有高论,结果是个思博题.随便找一条直径,最后答案肯定是这条直径上的连续一段,如果某分支长度等于直径上某端的长度这一端都要被剪掉. #include<iostream> #inclu ...

  4. [bzoj3124] [Sdoi2013]直径

    看了child学长的题解才知道怎么写TAT http://www.cnblogs.com/ctlchild/p/5160272.html 以前不知道直径都是过重心的..代码改着改着就和标程完全一样了Q ...

  5. 2018.11.05 bzoj3124: [Sdoi2013]直径(树形dp)

    传送门 一道sbsbsb树形dpdpdp 第一问直接求树的直径. 考虑第二问问的边肯定在同一条直径上均是连续的. 因此我们将直径记下来. 然后对于直径上的每一个点,dpdpdp出以这个点为根的子树中不 ...

  6. BZOJ3124 [Sdoi2013]直径 【树的直径】

    题目 小Q最近学习了一些图论知识.根据课本,有如下定义.树:无回路且连通的无向图,每条边都有正整数的权值来表示其长度.如果一棵树有N个节点,可以证明其有且仅有N-1 条边. 路径:一棵树上,任意两个节 ...

  7. BZOJ3124: [Sdoi2013]直径 (树形DP)

    题意:给一颗树 第一问求直径 第二问求有多少条边是所有直径都含有的 题解:求直径就不说了 解第二问需要自己摸索出一些性质 任意记录一条直径后 跑这条直径的每一个点  如果以这个点不经过直径能到达最远的 ...

  8. 【BZOJ3124】[Sdoi2013]直径 树形DP(不用结论)

    [BZOJ3124][Sdoi2013]直径 Description 小Q最近学习了一些图论知识.根据课本,有如下定义.树:无回路且连通的无向图,每条边都有正整数的权值来表示其长度.如果一棵树有N个节 ...

  9. [洛谷P3304] [SDOI2013]直径

    洛谷题目链接:[SDOI2013]直径 题目描述 小Q最近学习了一些图论知识.根据课本,有如下定义.树:无回路且连通的无向图,每条边都有正整数的权值来表示其长度.如果一棵树有N个节点,可以证明其有且仅 ...

  10. 3124: [Sdoi2013]直径

    3124: [Sdoi2013]直径 https://www.lydsy.com/JudgeOnline/problem.php?id=3124 分析: 所有直径都经过的边,一定都是连续的一段.(画个 ...

随机推荐

  1. 初学RunLoop

    RunLoop 运行循环,跑圈 可以看出每条线程都有一个与之对应的RunLoop对象 主线程的RunLoop已经自动创建好了,子线程的RunLoop需要主动创建. 基本作用:保持程序的持续运行 处理A ...

  2. [css]我要用css画幅画(三)

    接着之前的[css]我要用css画幅画(二), 今天,我画了一个小人,他的名字暂时叫作小明. 以下只列出本次修改增加的内容 html如下: <div class="human left ...

  3. yii2批量添加的问题

    作者:白狼 出处:http://www.manks.top/yii2_batch_insert.html 本文版权归作者,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否 ...

  4. C语言链表实现约瑟夫环问题

    需求表达:略 分析: 实现: #include<stdio.h> #include<stdlib.h> typedef struct node { int payload ; ...

  5. 记录一次MongoDB3.0.6版本wiredtiger与MMAPv1引擎的写入耗时对比

    一.MongoDB3.0.x的版本特性(相对于MongoDB2.6及以下): 增加了wiredtiger引擎: 开源的存储引擎: 支持多核CPU.充分利用内存/芯片级别缓存(注:10月14日刚刚发布的 ...

  6. java实现基于activeMQ的消息推送

    一. 准备工作 1. 点击此下载相关的第三方jar包,并在工程中引用 二. spring配置文件:application.xml <?xml version="1.0" en ...

  7. linux中文件(档案)和目录的RWX权限意义

    1 权限对文件的意义 权限对文件的意义很好理解,下面我们看看权限对目录的意义. 2 权限对目录的意义 档案是存放实际资料的所在,那么目录主要是储存啥玩意啊?目录主要的内容在记录档名清单,档名与目录有强 ...

  8. [django]l利用xlrd实现xls文件导入数据

    代码: #coding:utf-8 import os os.environ.setdefault("DJANGO_SETTINGS_MODULE", "www.sett ...

  9. 电信行业的BI应用

    截至2015年年底,我国三大运营商的移动用户数达到13.1亿户,4G /3G用户累计达到8.09亿户,再次创下新高.从三大运营商的年度财报来看,在具体业务方面,三大运营商的数据流量业务带来的收入均已超 ...

  10. Caffe源码解析5:Conv_Layer

    转载请注明出处,楼燚(yì)航的blog,http://home.cnblogs.com/louyihang-loves-baiyan/ Vision_layer里面主要是包括了一些关于一些视觉上的操 ...