hdu2856_how far away(tarjan/lca)

来源:互联网 发布:研究院所 软件 百分点 编辑:程序博客网 时间:2024/06/07 03:02
#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <cmath>#include <vector>#include <map>#define INF 0x3f3f3f3f#define rep0(i, n) for (int i = 0; i < n; i++)#define rep1(i, n) for (int i = 1; i <= n; i++)#define rep_0(i, n) for (int i = n - 1; i >= 0; i--)#define rep_1(i, n) for (int i = n; i > 0; i--)#define MAX(x, y) (((x) > (y)) ? (x) : (y))#define MIN(x, y) (((x) < (y)) ? (x) : (y))#define mem(x, y) memset(x, y, sizeof(x))#define MAXN 40000 + 10#define MAXM 200 + 10using namespace std;/**题目大意求树上任意两点之间的路径长度思路tarjan求lcadfs时各节点到根的距离ans = dp[u] + dp[v] - 2 * dp[lca]*/typedef long long LL;struct Edge{    int u, v, w;};struct query{    int a, b;    LL ans;} q[MAXM];vector<Edge> edges;vector<int> g[MAXN];int n, m, pa[MAXN];bool vis[MAXN];LL dp[MAXN];void addEdge(int u, int v, int w){    Edge e;    e.u = u;    e.v = v;    e.w = w;    edges.push_back(e);    g[u].push_back(edges.size() - 1);    g[v].push_back(edges.size() - 1);}int findset(int u){    if (pa[u] == u)        return u;    pa[u] = findset(pa[u]);    return pa[u];}void dfs(int u, int fa){    vis[u] = true;    for (int i = 0; i < g[u].size(); i++)    {        int v = (edges[g[u][i]].u == u) ? edges[g[u][i]].v : edges[g[u][i]].u;        if (v == fa)            continue;        dp[v] = edges[g[u][i]].w + dp[u];        dfs(v, u);        pa[v] = u;    }    for (int i = 0; i < m; i++)    {        if (q[i].a != u && q[i].b != u)            continue;        int v = (q[i].a == u) ? q[i].b : q[i].a;        if (vis[v])        {            int lca = findset(v);            q[i].ans = dp[v] + dp[u] - 2 * dp[lca];        }    }}int main(){    #ifndef ONLINE_JUDGE        freopen("in.txt", "r", stdin);    #endif // ONLINE_JUDGE    int t, u, v,  w;    scanf("%d", &t);    while (t--)    {        edges.clear();        scanf("%d %d", &n, &m);        mem(vis, 0);        for (int i = 1; i <= n; i++)            g[i].clear();        for (int i = 0; i < n - 1; i++)        {            scanf("%d %d %d", &u, &v, &w);            addEdge(u, v, w);            pa[i + 1] = i + 1;        }        pa[n] = n;        for (int i = 0; i < m; i++)        {            scanf("%d %d", &u, &v);            q[i].a = u;            q[i].b = v;        }        dp[1] = 0;        dfs(1, -1);        for (int i = 0; i < m; i++)        {            printf("%lld\n", q[i].ans);        }    }    return 0;}

原创粉丝点击