**
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 100
**
Sample Output
**
1110
2
【样例说明】
直径共有两条,3 到2的路径和3到6的路径。这两条直径都经过边(3, 1)和边(1, 4)。
HINT
对于100%的测试数据:2≤N≤200000,所有点的编号都在1..N的范围内,
边的权值≤10^9。
**
Source
**
**
Solution
**
做了bzoj1999差不多就可以想到这种做法了
先两边dfs找直径 然后做外向树【是叫这个吧……】
然后从一头跑呀跑~
如果当前遍历的节点的外向树上存在一条路径满足 到已经直径一段的距离相等 就说明那个端点也是直径
[没有节点的外向树 有节点的那条是直径]
比如我们遍历到了第三个节点 有两个外向树 如果至少有一个满足上述条件 那么之前经过的那些边一定不是所有直径经过的【想一想为什么?】
想明白上面的看下面的
直到一个mid!
然后我们在mid左面找到一个节点就跳出循环 输出答案就好了
至于为什么是long long
我会告诉你我WA了么……然后找了个std对拍……并没有什么发现……然后……
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=4e5+10;
struct data{ll to,next,w;}e[maxn*2];
ll head[maxn],cnt;
void ins(ll u,ll v,ll w){cnt++;e[cnt].to=v;e[cnt].next=head[u];head[u]=cnt;e[cnt].w=w;}
void insert(ll u,ll v,ll w){ins(u,v,w);ins(v,u,w);}
ll fa[maxn],last,end,st,ed,root,mx;
ll belong[maxn],ans,n;
bool vis[maxn];
long long dis[maxn];
void dfs(ll x)
{
vis[x]=1;
for(ll i=head[x];i;i=e[i].next)
if(!vis[e[i].to])
{
dis[e[i].to]=dis[x]+e[i].w;
if(mx<dis[e[i].to])
{
mx=dis[e[i].to];
root=e[i].to;
}
fa[e[i].to]=x;
dfs(e[i].to);
}
vis[x]=0;
}
int main()
{
//freopen("in.txt","r",stdin);
scanf("%lld",&n);
for(ll i=1;i<n;i++)
{
ll u,v,w;
scanf("%lld%lld%lld",&u,&v,&w);
insert(u,v,w);
}
dfs(1);st=root;mx=0;dis[st]=0;fa[st]=0;dfs(st);ed=root;
for(ll i=ed;i;i=fa[i])vis[i]=1;fa[0]=0;
for(ll i=ed;i;i=fa[i])
{
if(dis[i]==dis[ed]-dis[i])belong[i]=-1;
else belong[i]=(dis[i]<dis[ed]-dis[i])?st:ed;
long long len=dis[i];
dis[i]=0;mx=root=0;dfs(i);dis[i]=abs(dis[belong[i]]-len);vis[i]=1;
if(dis[root]==dis[i])
{
if(belong[i]==-1){printf("0");return 0;}
if(belong[i]==ed)last=i;
else {end=i;break;}
}
dis[i]=len;
}
if(!last)last=ed;
if(!end)end=st;
for(ll i=last;i!=end;i=fa[i])
ans++;
cout<<dis[ed]<<endl<<ans;
return 0;
}
——生且不惧,死又何妨