• bzoj 2870: 最长道路tree


    orz n+e的题解

    显然,将两棵树合并以后,新直径的两个端点一定在原来的两条直径的四个端点中。

    画个图就知道了(我竟然没看出来QAQ

    于是就可以从大到小枚举最小权,并查集合并了

    时间复杂度(O(nlogn))

    #include <bits/stdc++.h>
    #define N 60000
    using namespace std;
    int n;
    int vi[N];
    vector <int> bi[N];
    int shed[N], fa[N], fp[N], dep[N], fb[N];
    int lowbit(int t) {return t & (-t);}
    void dfs(int t, int d)
    {
        shed[d] = t; dep[t] = d; fa[t] = shed[d - 1]; fp[t] = shed[d - lowbit(d)];
        for (int i = 0; i < bi[t].size(); ++ i)
            if (bi[t][i] != fa[t])
                dfs(bi[t][i], d + 1);
    }
    int lca(int a, int b)
    {
        while (a != b)
        {
            if (dep[a] < dep[b]) swap(a, b);
            if (dep[a] > dep[b])
            {
                if (dep[fp[a]] < dep[b]) a = fa[a];
                else a = fp[a];
            }
            else 
            {
                if (fp[a] == fp[b]) a = fa[a], b = fa[b];
                else a = fp[a], b = fp[b];
            }
        }
        return a;
    }
    int get_fb(int t)
    {
        return fb[t] = fb[t] == t? t: get_fb(fb[t]);
    }
    int ai[N][2];
    int ls[N], vis[N];
    int comp(int a, int b) {return vi[a] > vi[b];}
    #define LL long long 
    LL ans;
    int main()
    {
        scanf("%d", &n);
        for (int i = 1; i <= n; ++ i)
            scanf("%d", &vi[i]);
        for (int i = 1; i <= n; ++ i) ls[i] = ai[i][0] = ai[i][1] = fb[i] = i;
        sort(ls + 1, ls + n + 1, comp);
        for (int i = 1; i < n; ++ i)
        {
            int a, b;
            scanf("%d%d", &a, &b);
            bi[a].push_back(b);
            bi[b].push_back(a);
        }
        dfs(1, 1);
        for (int q = 1; q <= n; ++ q)
        {
            int i = ls[q], mx = 0;
            vis[i] = 1;
            for (int j = 0; j < bi[i].size(); ++ j)
                if (vis[bi[i][j]])
                {
                    int x = get_fb(bi[i][j]);
                    int ll[4] = {ai[x][0], ai[x][1], ai[i][0], ai[i][1]};
                    for (int p0 = 0; p0 < 4; ++ p0)
                        for (int p1 = p0 + 1; p1 < 4; ++ p1)
                        {
                            int nw = dep[ll[p0]] + dep[ll[p1]] - dep[lca(ll[p0], ll[p1])] * 2;
                            if (nw > mx)
                            {
                                mx = nw;
                                ai[i][0] = ll[p0];
                                ai[i][1] = ll[p1];
                            }
                        }
                    fb[x] = i;
                }
            ans = max(ans, 1ll * (mx + 1) * vi[i]);
        }
        cout << ans;
    }
  • 相关阅读:
    软件工程课程总结
    《20171122-构建之法:现代软件工程-阅读笔记》
    课后作业-阅读任务-阅读提问-4
    20171012-构建之法:现代软件工程-阅读笔记
    课后作业-阅读任务-阅读提问-2
    《20170911-构建之法:现代软件工程-阅读笔记》
    OSI七层模型
    团队编程项目作业名称-团队一阶段互评
    结对-结对编程项目作业名称-结对项目总结
    团队-团队编程项目作业名称-开发文档
  • 原文地址:https://www.cnblogs.com/AwD-/p/6329538.html
Copyright © 2020-2023  润新知