zoukankan      html  css  js  c++  java
  • HRBUST 2064:萌萌哒十五酱的宠物~(最近公共祖先LCA)

    题意:一个n个点的树,询问某两点之间的简单路径,问路径上任选三边能否组成一个三角形。 N<100000,权值<109

    思路:

    这里最神奇的思路过于以下这个:

    n个数,任意三个都不能组成三角形,只有当:

    排序A,且A[i] >= A[i-1] + A[i-2];

    观察可以发现其增长类似斐波那契,又因为权值<109,所以当路径里边的个数>=45个时,必然可以组成三角形。

    剩下的,就暴力一下就好了。

    确定路径边的个数的方法是深度结合lca来做。暴力的话就是两点向上攀,直到公共祖先。然后sort一下,然后检查是否存在 A[i] < A[i-1] + A[i-2]就好了。

    代码:

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    #define N 100010
    
    struct BCJ{
        int fa[N];
        void init(int n) {
            for (int i = 0; i <= n; i++) fa[i] = i;
        }
        void unin(int u, int v) {
            fa[find(v)] = find(u);
        }
        int find(int u) {
            return fa[u] == u? fa[u] : fa[u] = find(fa[u]);
        }
    }comFa;
    struct faEdge{
        int fa;
        int c;
    }fa[N];
    int dep[N];
    
    struct Graph{
        struct Edge{
            int to, next, c;
        }e[N<<2];
        int head[N];
        int p;
        void init(){ 
            memset(head, -1, sizeof(head));
            p = 0;
        }
        void add(int u, int v, int len) {
            e[p].to = v;
            e[p].c = len;
            e[p].next = head[u];
            head[u] = p++;
        }
    }g, q;
    
    struct Query{
        int s,t,com;
    }que[N];
    
    void dfs(int now) {
        //printf("now = %d
    ", now);
        for (int i = g.head[now]; ~i; i = g.e[i].next) {
            int &to = g.e[i].to;
            //printf("to = %d
    ", to);
            if (dep[to] == -1) {
                dep[to] = dep[now]+1;
                fa[to].fa = now;
                fa[to].c = g.e[i].c;
                dfs(to);
                comFa.unin(now,to);
            }
        }
        for (int i = q.head[now]; ~i; i = q.e[i].next) {
            int &to = q.e[i].to;
            if (dep[to] != -1) {
                que[q.e[i].c].com = comFa.find(to);
            }
        }
    }
    
    int a[N];
    
    int main() {
        int n;
        while (scanf("%d", &n) != EOF) {
            g.init();
            for (int i = 0; i < n-1; i++) {
                int a, b, len;
                scanf("%d%d%d", &a, &b, &len);
                g.add(a,b,len);
                g.add(b,a,len);
            }
    
            int m;
            scanf("%d", &m);
            q.init();
            for (int i = 0; i < m; i++) {
                int s, t;
                scanf("%d%d", &s, &t);
                que[i].s = s;
                que[i].t = t;
                q.add(s,t,i);
                q.add(t,s,i);
            }
            memset(dep, -1, sizeof(dep));
            dep[1] = 0;
            fa[1].fa = 1;
            fa[1].c = 0;
            comFa.init(n);
            dfs(1);
            for (int i = 0; i < m; i++) {
                int nodeNum = dep[que[i].s] + dep[que[i].t] - 2*dep[que[i].com];
                if (nodeNum >= 45) {
                    puts("Yes");
                } else {
                    int top = 0;
                    for (int j = que[i].s; j != que[i].com; j = fa[j].fa) {
                        a[top++] = fa[j].c;
                    }
                    for (int j = que[i].t; j != que[i].com; j = fa[j].fa) {
                        a[top++] = fa[j].c;
                    }
                    sort(a,a+top);
                    bool ok = false;
                    for (int i = 2; i < top; i++) {
                        if (a[i] < a[i-1]+a[i-2]) {
                            ok = true;
                            break;
                        }
                    }
                    puts(ok?"Yes":"No");
                }
            }
        }
        return 0;
    }
  • 相关阅读:
    Web中Servlet简单总结
    JavaSE进阶的面试题
    多线程简单总结
    Java基础集合简单总结
    内部类和Lambda
    多态
    接口
    继承
    uni-app 中uCharts
    vue 组件传值
  • 原文地址:https://www.cnblogs.com/shinecheng/p/3623985.html
Copyright © 2011-2022 走看看