[Sdoi2013] 直径

Posted Forever_goodboy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[Sdoi2013] 直径相关的知识,希望对你有一定的参考价值。

[Sdoi2013]直径

时间限制: 1 Sec  内存限制: 256 MB

题目描述

小Q最近学习了一些图论知识。根据课本,有如下定义。树:无回路且连通的无向图,每条边都有正整数的权值来表示其长度。如果一棵树有N个节点,可以证明其有且仅有N-1 条边。 路径:一棵树上,任意两个节点之间最多有一条简单路径。我们用 dis(a,b)
表示点a和点b的路径上各边长度之和。称dis(a,b)为a、b两个节点间的距离。  
 直径:一棵树上,最长的路径为树的直径。树的直径可能不是唯一的。 
现在小Q想知道,对于给定的一棵树,其直径的长度是多少,以及有多少条边满足所有的直径都经过该边。 

输入

第一行包含一个整数N,表示节点数。 
接下来N-1行,每行三个整数a, b, c ,表示点 a和点b之间有一条长度为c
的无向边。 

输出

  
共两行。第一行一个整数,表示直径的长度。第二行一个整数,表示被所有
直径经过的边的数量。 

样例输入

 
6 
3  1 1000
1  4 10
4  2 100
4  5 50
4  6 100

样例输出

1110 
2 
 
【样例说明】 
直径共有两条,3 到2的路径和3到6的路径。这两条直径都经过边(3, 1)和边(1, 4)。

提示

对于100%的测试数据:2≤N≤200000,所有点的编号都在1..N的范围内。

Solution:
    自己瞎yy了一下,然后就过了,很懵逼。直径很好求,求完以后直接记录一下直径上的点然后检查一下是否还有等长的就好。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 using namespace std;
 6 #define int long long
 7 #define N 200005
 8 #define root 1
 9 int read() {
10     int s=0,f=1;
11     char ch=getchar();
12     for( ; ch<0||ch>9; f=(ch==-)?-1:f,ch=getchar()) ;
13     for( ; ch>=0&&ch<=9; s=s*10+(ch^48),ch=getchar()) ;
14     return s*f;
15 }
16 int n,tot,r[N],Fa[N],low,high,Dis,deep[N],dis[N],Ans2;
17 struct oo {int fr,to,next,vv;} c[N<<1|1];
18 bool vis[N],Up[N],Down[N];
19 void add(int x,int y,int z) {
20     c[++tot].fr=x;
21     c[tot].to=y;
22     c[tot].vv=z;
23     c[tot].next=r[x];
24     r[x]=tot;
25 }
26 void dfs1(int u,int f,int d) {
27     if(d>Dis) Dis=d,low=u;
28     for(int i=r[u]; ~i; i=c[i].next) if(c[i].to!=f) dfs1(c[i].to,u,d+c[i].vv);
29 }
30 void dfs2(int u,int f) {
31     if(deep[u]>Dis) Dis=deep[u],high=u;
32     for(int i=r[u]; ~i; i=c[i].next) {
33         if(c[i].to!=f) {
34             Fa[c[i].to]=u,dis[c[i].to]=dis[u]+1;
35             deep[c[i].to]=deep[u]+c[i].vv;
36             dfs2(c[i].to,u);
37         }
38     }
39 }
40 void dfs(int u,int f,int d,int &mx) {
41     mx=max(mx,d);
42     for(int i=r[u]; ~i; i=c[i].next) if(c[i].to!=f&&!vis[c[i].to]) dfs(c[i].to,u,d+c[i].vv,mx);
43 }
44 signed main() {
45     n=read();
46     memset(r,0xff,sizeof(r));
47     for(int x,y,z,i=1; i<n; ++i) {
48         x=read(),y=read(),z=read();
49         add(x,y,z),add(y,x,z);
50     } dfs1(root,root,0); Dis=0; dfs2(low,low);
51     for(int i=high; i!=low; i=Fa[i]) vis[i]=true;
52     vis[low]=true;
53     for(int i=high,mx=0; ; i=Fa[i],mx=0) {
54         dfs(i,i,0,mx);
55         if(mx==deep[i]) Up[i]=true;
56         if(mx==Dis-deep[i]) Down[i]=true;
57         if(i==low) break;
58     } int pos1=0,pos2=0;
59     for(int i=high; ; i=Fa[i]) {
60         if(Up[i]&&!pos1) pos1=i;
61         if(Down[i]) pos2=i;
62         if(i==low) break;
63     } Ans2=dis[pos2]-dis[pos1];
64     if(Ans2<0) Ans2=0;
65     printf("%lld\n%lld",Dis,Ans2);
66     return 0;
67 }

 

以上是关于[Sdoi2013] 直径的主要内容,如果未能解决你的问题,请参考以下文章

[SDOI2013]直径(树的直径)

[树的直径] SDOI2013 直径

[Sdoi2013]直径(树的直径)

[SDOI2013]直径 (树的直径,贪心)

P3304 [SDOI2013]直径(模板树直径的必经边)

Bzoj 3124: [Sdoi2013]直径 题解