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\n", now);
    for (int i = g.head[now]; ~i; i = g.e[i].next) {
        int &to = g.e[i].to;
        //printf("to = %d\n", 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;
}

 

posted on 2014-03-25 19:47  ShineCheng  阅读(212)  评论(0编辑  收藏  举报

导航