[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 10001 4 104 2 1004 5 504 6 100样例输出
1110 2 【样例说明】 直径共有两条,3 到2的路径和3到6的路径。这两条直径都经过边(3, 1)和边(1, 4)。提示
对于100%的测试数据:2≤N≤200000,所有点的编号都在1..N的范围内。
Solution: 自己瞎yy了一下,然后就过了,很懵逼。直径很好求,求完以后直接记录一下直径上的点然后检查一下是否还有等长的就好。
1 #include2 #include 3 #include 4 #include 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