[SDOI2013] 直径 - 树形dp

对于给定的一棵树,其直径的长度是多少,以及有多少条边满足所有的直径都经过该边。

Solution

有点意思

先随便求一条直径(两次DFS即可),不妨设为 \(s,t\),我们知道要求的这些边一定都在这条路径上,不妨将它看作一条线(用DFS + STACK把它提取出来),其中 \(s\) 叫左边, \(t\) 叫右边

我们现在就要在这条线上借出一段区间

考虑如何求它的右端点,以 \(s\) 为根跑 DFS,算出每个点子树的最长路径以及条数

\(t\) 往左扫,如果碰到某条边不是必须经过的边(可以根据 \(u,v\) 的最长路条数关系判断),就把它记下来

那么最后一次被记下来的边的左端点就是目标区间的右端点

左端点同理即可

#include 
using namespace std;

#define int long long
const int N = 200005;

vector  > 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>n;
    for(int i=1;i>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<

你可能感兴趣的:([SDOI2013] 直径 - 树形dp)