bzoj3124[Sdoi2013]直径(树dp)
来源:互联网 发布:泰语字母发音软件 编辑:程序博客网 时间:2024/05/17 04:46
Description
小Q最近学习了一些图论知识。根据课本,有如下定义。树:无回路且连通的无向图,每条边都有正整数的权值来表示其长度。如果一棵树有N个节点,可以证明其有且仅有N-1 条边。 路径:一棵树上,任意两个节点之间最多有一条简单路径。我们用 dis(a,b)
表示点a和点b的路径上各边长度之和。称dis(a,b)为a、b两个节点间的距离。
直径:一棵树上,最长的路径为树的直径。树的直径可能不是唯一的。
现在小Q想知道,对于给定的一棵树,其直径的长度是多少,以及有多少条边满足所有的直径都经过该边。Input
第一行包含一个整数N,表示节点数。
接下来N-1行,每行三个整数a, b, c ,表示点 a和点b之间有一条长度为c
的无向边。Output
共两行。第一行一个整数,表示直径的长度。第二行一个整数,表示被所有
直径经过的边的数量。Sample Input
6
3 1 1000
1 4 10
4 2 100
4 5 50
4 6 100Sample Output
1110
2
第一问很简单,两边dfs即可。
对于第二问,我们需要注意到以下几点
(设直径较浅的端点为
1.答案一定在已经确定出的直径上
2.当存在一段由
所以我们可以先求出一条直径,同时dp出不与直径相交的最长路径长度,然后统计出合法区间中的点数即可.
代码
#include <cstdio>#include <cstring>#define maxn 200005#define maxx 400005#define mem(a,b) memset(a,b,sizeof(a))inline void read(int& x){ char c=getchar();x=0;int y=1; while(c<'0'||c>'9'){if(c=='-') y=-1;c=getchar();} while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar(); x*=y;}typedef long long ll;ll dp[maxn],f[maxn],ans;int n,num,hea[maxn],lef[maxn],rig[maxn],cnt,range,target,retarget,upside,downside;bool used;struct road{int en,w,nex;}ro[maxx];inline void add(int x,int y,int z){ro[num].en=y;ro[num].nex=hea[x];ro[num].w=z;hea[x]=num++;}inline void dfs(int x,int y=0,ll z=0){ if(z>ans) ans=z,target=x; for(int i=hea[x];i!=-1;i=ro[i].nex) { int v=ro[i].en; if(v==y) continue; dfs(v,x,z+ro[i].w); }}inline void redfs(int x,int y=0,ll z=0){ lef[x]=rig[x]=++cnt;dp[x]=z; if(ans<z) ans=z,retarget=x,range=lef[x]; for(int i=hea[x];i!=-1;i=ro[i].nex) { int v=ro[i].en; if(v==y) continue; redfs(v,x,z+ro[i].w); if(f[x]<f[v]+ro[i].w) f[x]=f[v]+ro[i].w; } rig[x]=cnt;}inline void dfs3(int x,int y=0){ ll fir=0; for(int i=hea[x];i!=-1;i=ro[i].nex) { int v=ro[i].en;if(v==y) continue; if(lef[v]<=range&&rig[v]>=range) dfs3(v,x); else if(fir<f[v]+ro[i].w) fir=f[v]+ro[i].w; } if(!used&&fir==dp[x]) upside=x,used=1; if(fir==(dp[retarget]-dp[x])) downside=x;}inline void dfs4(int x,int y=0){ if(dp[x]>=dp[upside]&&dp[x]<=dp[downside]) ++ans; for(int i=hea[x];i!=-1;i=ro[i].nex) { int v=ro[i].en;if(v==y) continue; if(lef[v]<=range&&rig[v]>=range) dfs4(v,x); }}int main(){ read(n);mem(hea,-1);int x=0,y=0,z=0; for(int i=1;i<n;++i) { read(x);read(y);read(z); add(x,y,z);add(y,x,z); } dfs(1);ans=0;redfs(target);printf("%lld\n",ans); dfs3(target);ans=0;dfs4(target); printf("%lld",ans-1); return 0;}
阅读全文
0 0
- bzoj3124[Sdoi2013]直径(树dp)
- bzoj3124 [Sdoi2013]直径 直径+树形dp
- bzoj3124 [Sdoi2013]直径 树的直径
- [BZOJ3124][Sdoi2013]直径(树形dp)
- [BZOJ3124][Sdoi2013]直径(树形dp)
- 【bzoj3124】: [Sdoi2013]直径
- BZOJ3124: [Sdoi2013]直径
- [BZOJ3124][SDOI2013]直径(DFS)
- BZOJ3124 [sdoi2013]直径(树上的dfs)
- Bzoj3124 [SDO2013]直径
- 【SDOI2013】直径
- [Sdoi2013]直径
- 【sdoi2013】直径
- 3124: [Sdoi2013]直径【dfs】【树的直径】【外向树】
- bzoj3124(树形dp)
- 【JZOJ3213】【SDOI2013】直径
- BZOJ 3124 [Sdoi2013]直径 DFS
- HDU4607(最大直径 树DP)
- java基础-head first 设计模式
- asp.net C# config 自定义节点及自定义节点配置以独立文件存在
- KNN
- C#之常量使用
- 插旗立flag
- bzoj3124[Sdoi2013]直径(树dp)
- 动作游戏(ACT)——棱角战士(基于Unity3D 5.4.2)
- Python高级编程——1.包(lib)和模块(module)
- MapReduce学习笔记
- C++使用thread类多线程编程
- memcached安装报错解决
- 2017CCPC(秦皇岛站)总结
- oracle的一些使用技巧1
- BCOS多主机联网