• 漂亮的公园


    ps:再再再再次感觉自己好菜!此题有个结论:对于一棵树,给定一个点集S,设其最远的两个点为x,y。其它点u到这个点集S的最远距离,必然是到u到x的距离或者是u到y的距离。这样两个集合之间的距离就转化为4个点距离!!!!怎么求每个集合的最远的两个点呢?还是同样的方法,取该集合的两个点作为最远的两个点(直径(不是树的直径)),然后依次加入该集合的其它点,更新即可。集合的直径与如入元素的顺序无关!

    const int N = 100005;
    
    struct LCA {
        vector<int> G[N];
        int n, d[N], pa[N][20];
    
        void Inite(int cnt) {
            n = cnt;
            mem(pa, 0);
        }
        void addedge(int u, int v) {
            G[u].pb(v);
            G[v].pb(u);
        }
        void DFS(int u, int fa, int dep) {
            d[u] = dep;
            pa[u][0] = fa;
            for (auto v : G[u]) if (v != fa) DFS(v, u, dep + 1);
        }
        void ST() {
            DFS(1, 0, 0);
            for (int i = 1; (1 << i) <= n; ++i) {
                for (int j = 1; j <= n; ++j) if (pa[j][i - 1]) pa[j][i] = pa[pa[j][i - 1]][i - 1];
            }
        }
        int getLca(int u, int v) {
            if (d[u] > d[v]) swap(u, v);
    
            rep(i, 0, 20) if ((d[v] - d[u]) & (1 << i)) v = pa[v][i];
            if (u == v) return u;
    
            for (int i = 19; ~i; --i) if (pa[u][i] != pa[v][i]) {
                u = pa[u][i];
                v = pa[v][i];
            }
            return pa[u][0];
        }
        int computed(int u, int v) {
            int fa = getLca(u, v);
            return (d[u] + d[v] - 2 * d[fa]);
        }
    };
    
    LCA lca;
    
    P od[N];  // 记录每个集合的直径(最远的两个点)
    int n, q, tot;
    
    vector<int> p[N];
    
    map<int, int> c;
    
    int main()
    {
        sc(n), sc(q);
        Rep(i, 1, n) {
            int u;
            sc(u);
            if (!c[u]) c[u] = ++tot;
            p[c[u]].pb(i);
        }
    
        lca.Inite(n);
    
        rep(i, 1, n) {
            int u, v;
            sc(u), sc(v);
            lca.addedge(u, v);
        }
    
        lca.ST();
    
        Rep(i, 1, tot) {
            od[i].first = od[i].second = p[i][0];
            int last = 0;
            rep(j, 1, p[i].size()) {
                int l = lca.computed(p[i][j], od[i].first);
                int r = lca.computed(p[i][j], od[i].second);
                if (l >= r && l > last) {
                    od[i].second = p[i][j];
                    last = l;
                }
                else if (r >= l && r > last) {
                    od[i].first = p[i][j];
                    last = r;
                }
            }
        }
        while(q--) {
            int x, y, res = 0;
            sc(x), sc(y);
            if (!c[x] || !c[y]) puts("0");
            else if (c[x] == c[y]) {
                int res = lca.computed(od[c[x]].first, od[c[x]].second);
                pr(res);
            }
            else {
                int t1 = lca.computed(od[c[x]].first, od[c[y]].first);
                if (t1 > res) res = t1;
                int t2 = lca.computed(od[c[x]].first, od[c[y]].second);
                if (t2 > res) res = t2;
                int t3 = lca.computed(od[c[x]].second, od[c[y]].first);
                if (t3 > res) res = t3;
                int t4 = lca.computed(od[c[x]].second, od[c[y]].second);
                if (t4 > res) res = t4;
                pr(res);
            }
        }
        return 0;
    }
  • 相关阅读:
    一些至理名言
    移除快捷方式上面那个丑陋的小箭头
    一些浏览器插件
    yahoo给出的关于网站优化的建议
    javascript 事件流
    关于mongodb的一些笔记
    WebStorm
    给go添加各种package
    工具类 util.Date 日期类
    几种简单排序算法
  • 原文地址:https://www.cnblogs.com/zgglj-com/p/9640609.html
Copyright © 2020-2023  润新知