您的位置:首页 > 其它

LCA小结

2015-09-13 21:29 337 查看
概念

算法

ST算法(在线)

[code]#include <cstdio>
#include <cstring>
const int MAXNODE = 100010;
const int MAXEDGE = 200010;

struct Edge {
    int u, v, next;
    Edge() {}
    Edge(int u, int v, int next): u(u), v(v), next(next) {}
};

struct ST {
    Edge edges[MAXEDGE];
    int n, m, tot;
    int head[MAXNODE], depth[MAXNODE], first[MAXNODE], ver[MAXNODE];
    int dp[MAXNODE][64];
    bool vis[MAXNODE];

    void init(int n) {
        this->n = n;
        m = tot = 0;
        memset(head, -1, sizeof(head));
        memset(vis, 0, sizeof(vis));
    }

    void AddEdge(int u, int v) {
        edges[m] = Edge(u, v, head[u]);
        head[u] = m++;
    }

    //ver记录的是第tot个结点是哪个,first记录的是结点u第一次出现的位置,depth记录的是第tot个结点的深度
    void dfs(int u, int dep) {
        vis[u] = true; ver[++tot] = u; first[u] = tot; depth[tot] = dep;
        for (int i = head[u]; ~i; i = edges[i].next) {
            int v = edges[i].v;
            if (!vis[v]) {
                dfs(v, dep + 1);
                ver[++tot] = u; depth[tot] = dep;
            }
        }
    }

    void RMQ() {

        //dp记录的是下标从i开始,长度为2的j次方这段区间内深度最小的点是ver中的第几个
        for (int i = 1; i <= tot; i++)
            dp[i][0] = i;
        int a, b;
        for (int j = 1; (1 << j) <= tot; j++) 
            for (int i = 1; i + (1 << j) - 1 <= tot; i++) {
                a = dp[i][j - 1];
                b = dp[i + (1 << (j - 1))][j - 1];
                if (depth[a] < depth) 
                    dp[i][j] = a;
                else
                    dp[i][j] = b;
            }
    }

    void solve(int root) {
        dfs(root, 1);
        RMQ();
    }

    //查询区间[x,y]中深度最小的那个数的位置
    int Query(int x, int y) {
        int k = 0;
        while (1 << (k + 1) <= y - x + 1) k++;
        int a = dp[x][k];
        int b = dp[y - (1 << k) + 1][k];
        if (depth[a] < depth[b]) return a;
        return b;
    }

    int LCA(int x, int y) {
        x = first[x];
        y = first[y];
        if (x > y) {
            x = x ^ y; y = x ^ y; x = x ^ y;
        }
        int c = Query(x, y);
        return ver[c];
    }

}st;

int main() {
    return 0;
}


tarjan离线算法

[code]#include <cstdio>
#include <cstring>

const int MAXNODE = 40010;
const int MAXEDGE = 80010;
typedef int Type;
const Type INF = 0x3f3f3f3f; //1e20

struct Edge{
    int u, v, next;
    Type dis;
    Edge() {}
    Edge(int u, int v, int next, Type dis): u(u), v(v), next(next), dis(dis) {}
};

struct Question{
    int u, v, next;
    bool ok;
    Question() {}
    Question(int u, int v, int next): u(u), v(v), next(next), ok(false){}
};

struct Tarjan{
    Edge edges[MAXEDGE];
    Question ques[MAXNODE];
    int n, m, q;
    int EdgeHead[MAXNODE], f[MAXNODE], LCA[MAXNODE], QuesHead[MAXNODE];
    bool vis[MAXNODE];
    Type dis[MAXNODE];

    void init(int n) {
        this->n = n;
        m = q = 0;
        memset(vis, 0, sizeof(vis));
        memset(EdgeHead, -1, sizeof(EdgeHead));
        memset(QuesHead, -1, sizeof(QuesHead));
        memset(LCA, 0, sizeof(LCA));
    }

    void AddEdge(int u, int v, Type dis) {
        edges[m] = Edge(u, v, EdgeHead[u], dis);
        EdgeHead[u] = m++;
    }

    void AddQues(int x, int y) {
        ques[q] = Question(x, y, QuesHead[x]);
        QuesHead[x] = q++;
    }

    int find(int x) {
        return x == f[x] ? x : f[x] = find(f[x]);
    }

    //tarjan,遍历u结点的所有结点,并将u结点的所有直系子节点的父亲设为u,再进行查询
    void dfs(int u) {
        f[u] = u;
        vis[u] = true;
        for (int i = EdgeHead[u]; ~i; i = edges[i].next) {
            int v = edges[i].v;
            if (!vis[v]) {
                dis[v] = dis[u] + edges[i].dis;
                dfs(v);
                f[v] = u;
            }
        }

        //查询,如果其中一个结点刚好是u,且另一个结点已经遍历过,则u和v的LCA就是f[v]
        for (int i = QuesHead[u]; ~i; i = ques[i].next) {
            if (ques[i].ok) continue;
            int v = ques[i].v;
            if (vis[v]) {
                LCA[i] = find(v);
                ques[i].ok = ques[i ^ 1].ok = true;
            }
        }
    }
}tarjan;

int main() {
    return 0;
}


[b]题目


HDU - 2460 Network 边双连通+LCA

HDU - 2586 How far away ?LCA模版题

HDU - 2874 Connections between cities 森林+LCA

HDU - 3078 Network

POJ - 2763 Housewife Wind LCA+暴力

POJ - 3728 The merchant dp+LCA(好题)

POJ - 3417 Network LCA+dp

POJ - 1986 Distance Queries LCA模版

POJ - 1330 Nearest Common Ancestors LCA模版

POJ - 1470 Closest Common Ancestors LCA模版

SPOJ - QTREE2 Query on a tree II 暴力+LCA

UVALive - 4960 Sensor network 生成树+LCA

UVA - 11354 Bond 生成树+LCA
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: