• [SDOI2013] 直径


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

    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;
    }
    
  • 相关阅读:
    JavaScript 随机产生十个整数,放入数组中,对这个数组进行降序排序,并获取到这个数组的最大值和最小值
    JavaScript输出换行
    JavaScript超时调用、间歇调用
    JavaScript内置对象
    JavaScript事件列表
    JavaScript 中 for-in和 for-of 的区别
    JavaScript break指定标签打破多层循环示例
    初识JavaScript
    HTML + CSS CSS设置背景图片后图片没有铺满屏幕等
    设计模式之工厂模式
  • 原文地址:https://www.cnblogs.com/mollnn/p/12294846.html
Copyright © 2020-2023  润新知