【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 分析: 所有直径都经过的边,一定都是连续的一段.(画个 ...
随机推荐
- 在 ASP.NET MVC 中充分利用 WebGrid (microsoft 官方示例)
在 ASP.NET MVC 中充分利用 WebGrid https://msdn.microsoft.com/zh-cn/magazine/hh288075.aspx Stuart Leeks 下载代 ...
- Linux如何查看JDK的安装路径
如何在一台Linux服务器上查找JDK的安装路径呢? 有那些方法可以查找定位JDK的安装路径?是否有一些局限性呢? 下面总结了一下如何查找JDK安装路径的方法. 1:echo $JAVA_HOME ...
- backup, file manipulation operations (such as ALTER DATABASE ADD FILE) and encryption changes on a database must be serialized.
昨天在检查YourSQLDba备份时,发现有台数据库做备份时出现了下面错误信息,如下所示: <Exec> <ctx>yMaint.ShrinkLog</ctx> ...
- Ajax的笔记
Ajax指异步JavaScript及XML(Asynchronous JavaScipt And XML),是一种异步交互式网页开发技术,用于创建快速动态网页.与服务器进行少量数据交换中,Ajax可以 ...
- 修改AndroidStudio中的Logcat中的默认设置
按Ctrl+Alt+S打开Settings 在左上角的输入框中输入Locat 点右边的使用内部样式取消掉,好了,开始自定义吧.
- 【Windows编程】系列第二篇:Windows SDK创建基本控件
在Win32 SDK环境下,怎么来创建常用的那些基本控件呢?我们知道如果用MFC,简单的拖放即可完成大多数控件的创建,但是我们既然是用Windows SDK API编程,当然是从根上解决这个问题,实际 ...
- Linux File Recovery Study
Background Today I did stupid things that I went into the ~/Downloads/ and pressed [Alt] + [A] then ...
- POJ1961[KMP 失配函数]
Period Time Limit: 3000MS Memory Limit: 30000K Total Submissions: 16776 Accepted: 8077 Descripti ...
- python高级之多线程
python高级之多线程 本节内容 线程与进程定义及区别 python全局解释器锁 线程的定义及使用 互斥锁 线程死锁和递归锁 条件变量同步(Condition) 同步条件(Event) 信号量 队列 ...
- android第一行代码-1.项目结构
0.项目结构 一个简单的android项目结构大致如下 入口就是MainActivity这个类,如果对于一个陌生的项目,最好的办法是看AndroidMainifest.xml,如下 <?xml ...