对于给定的一棵树,其直径的长度是多少,以及有多少条边满足所有的直径都经过该边。
Solution
有点意思
先随便求一条直径(两次DFS即可),不妨设为 (s,t),我们知道要求的这些边一定都在这条路径上,不妨将它看作一条线(用DFS + STACK把它提取出来),其中 (s) 叫左边, (t) 叫右边
我们现在就要在这条线上借出一段区间
考虑如何求它的右端点,以 (s) 为根跑 DFS,算出每个点子树的最长路径以及条数
从 (t) 往左扫,如果碰到某条边不是必须经过的边(可以根据 (u,v) 的最长路条数关系判断),就把它记下来
那么最后一次被记下来的边的左端点就是目标区间的右端点
左端点同理即可
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 200005;
vector <pair<int,int> > g[N];
int n,x[N],y[N],top;
namespace sol1 {
int vis[N],dis[N],s,t,len;
void dfs(int p) {
vis[p]=1;
for(int i=0;i<g[p].size();i++) {
int q=g[p][i].first, w=g[p][i].second;
if(vis[q]==0) {
dis[q]=dis[p]+w;
dfs(q);
}
}
}
void solve() {
int tmp=0;
dfs(1);
for(int i=1;i<=n;i++) {
if(dis[tmp]<dis[i]) tmp=i;
}
s=tmp;
memset(vis,0,sizeof vis);
memset(dis,0,sizeof dis);
dfs(s);
for(int i=1;i<=n;i++) {
if(dis[tmp]<dis[i]) tmp=i;
}
t=tmp;
len=dis[tmp];
}
}
namespace sol2 {
int vis[N],s,t;
bool dfs(int p) {
vis[p]=1;
if(p==s) return 1;
for(int i=0;i<g[p].size();i++) {
int q=g[p][i].first, w=g[p][i].second;
if(vis[q]==0) {
int tmp = dfs(q);
if(tmp) {
x[++top]=q;
y[top]=w;
return 1;
}
}
}
}
void solve(int _s,int _t ){
s=_s; t=_t;
dfs(t);
x[++top]=t;
}
}
namespace sol3 {
int vis[N],f[N],h[N];
void dfs(int p) {
vis[p]=1;
h[p]=1;
for(int i=0;i<g[p].size();i++) {
int q=g[p][i].first, w=g[p][i].second;
if(vis[q]==0) {
dfs(q);
if(f[p]<f[q]+w) {
f[p]=f[q]+w;
h[p]=0;
}
if(f[p]==f[q]+w) h[p]+=h[q];
}
}
}
int solve(int s) {
dfs(s);
int ans=top;
//for(int i=1;i<=top;i++) cout<<h[x[i]]<<" ";
//cout<<endl;
for(int i=top-1;i;--i) {
if(h[x[i]]!=h[x[i+1]]) ans=i;
}
return ans;
}
}
namespace sol4 {
int vis[N],f[N],h[N];
void dfs(int p) {
vis[p]=1;
h[p]=1;
for(int i=0;i<g[p].size();i++) {
int q=g[p][i].first, w=g[p][i].second;
if(vis[q]==0) {
dfs(q);
if(f[p]<f[q]+w) {
f[p]=f[q]+w;
h[p]=0;
}
if(f[p]==f[q]+w) h[p]+=h[q];
}
}
}
int solve(int s) {
dfs(s);
int ans=1;
//for(int i=1;i<=top;i++) cout<<h[x[i]]<<" ";
//cout<<endl;
for(int i=2;i<=top;i++) {
if(h[x[i]]!=h[x[i-1]]) ans=i;
}
return ans;
}
}
signed main() {
ios::sync_with_stdio(false);
cin>>n;
for(int i=1;i<n;i++) {
int t1,t2,t3;
cin>>t1>>t2>>t3;
g[t1].push_back(make_pair(t2,t3));
g[t2].push_back(make_pair(t1,t3));
}
sol1::solve();
int s=sol1::s, t=sol1::t;
sol2::solve(s,t);
int ans1=sol3::solve(s);
int ans2=sol4::solve(t);
cout<<sol1::len<<endl<<ans1-ans2<<endl;
}