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;
}

 

posted @ 2017-01-20 22:23  AwD!  阅读(268)  评论(0编辑  收藏  举报