ZOJ 3195(LCA模板)

来源:互联网 发布:淘宝双十一价格规则 编辑:程序博客网 时间:2024/06/03 18:55

题意:给一个带权图 然后q个询问 每个询问有三个数x y z,求x y z这三个点连接起来需要多少距离。

LCA 对于每个询问求出任意两个点对的LCA 加和 / 2。


#include <iostream>#include <algorithm>#include <cstdio>#include <cstring>#include <cstdlib>#include <vector>#include <queue>using namespace std;const int dx[] = {-1, 0, 1, 0};const int dy[] = {0, 1, 0, -1};const int maxn = 50000 + 7;const int INF = ~0U >> 1;struct node { int v, val; };struct ask  { int u, v, lca; };vector<node> G[maxn];vector<ask> e;vector<int> query[maxn];int p[maxn], ans[maxn], d[maxn], vis[maxn];int n, q;int Find(int x) {    return p[x] == x ? x : p[x] = Find(p[x]);}void addEdge(int u, int v, int val) {    G[u].push_back((node) {v, val});    G[v].push_back((node) {u, val});}void addAsk(int u, int v) {    e.push_back((ask) {u, v, -1});    e.push_back((ask) {v, u, -1});    int len = e.size() - 1;    query[u].push_back(len - 1);    query[v].push_back(len);}void init() {    for(int i = 0; i < n; ++i) p[i] = i, G[i].clear(), query[i].clear();    memset(d, 0, sizeof(d));    memset(vis, 0, sizeof(vis));    memset(ans, 0, sizeof(ans));    e.clear();}void Tarjan(int u, int val) {    vis[u] = 1;    ans[u] = u;    d[u] = val;    for(int i = 0; i < G[u].size(); ++i) {        node& to = G[u][i];        if(!vis[to.v]) {            Tarjan(to.v, val + to.val);            int x = Find(u), y = Find(to.v);            if(x != y) p[to.v] = u;        }    }    for(int i = 0; i < query[u].size(); ++i) {        int w = query[u][i];        ask& temp = e[w];        if(vis[temp.v]) temp.lca = e[w^1].lca = ans[Find(temp.v)];    }}int main() {    int u, v, val;    int kase = 0;    while(scanf("%d", &n) != EOF) {        init();        for(int i = 0; i < n - 1; ++i) {            scanf("%d%d%d", &u, &v, &val);            addEdge(u, v, val);        }        scanf("%d", &q);        int x, y, z;        for(int i = 0; i < q; ++i) {            scanf("%d%d%d", &x, &y, &z);            addAsk(x, y);            addAsk(x, z);            addAsk(y, z);        }        if(kase) puts("");        kase++;        Tarjan(0, 0);        int ans = 0;        for(int i = 0; i < 3 * q; ++i) {            ans += (d[e[i*2].u] + d[e[i*2].v] - 2 * d[e[i*2].lca]);            if(i % 3 == 2) {                printf("%d\n", ans / 2);                ans = 0;            }        }    }    return 0;}


0 0
原创粉丝点击