HDU 2586How far away ? tarjan算法求LCA

来源:互联网 发布:mac中病毒了怎么办 编辑:程序博客网 时间:2024/05/21 18:44

题目:http://acm.hdu.edu.cn/showproblem.php?pid=2586


题意:有n个顶点,n - 1条双向边构成树,每条边都有权值,有m个查询,求每个查询两点之间的最小权值


思路:很久很久以前学最短路时用dijkstra把这题过了。。。用LCA求的话,求出从根节点到每个点之间的权值和,用dist[i]表示,那么对于查询(v, u)就有 dist[v, u] = dist[v] + dist[u] - 2 * dist[LCA(v, u)],很容易证明这个等式。另外这道题里面的边是双向边,但我建的是单向边,并没有什么影响


总结:居然卡在输出哪里,tarjan求lca,结果并不按查询顺序输出。。。淡淡的忧伤

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int N = 40010;typedef long long ll;struct edge{    int to, cost, next;}G1[N*2];struct node{    int to, ind, next;}G2[N];int head1[N], head2[N], par[N];int cnt1, cnt2;ll dist[N], res[N];bool vis[N];int n, m;void init(){    for(int i = 1; i <= n; i++)        par[i] = i;    memset(head1, -1, sizeof head1);    memset(head2, -1, sizeof head2);    memset(vis, 0, sizeof vis);    cnt1 = cnt2 = 0;}void add_edge1(int v, int u, int c){    G1[cnt1].to = u;    G1[cnt1].cost = c;    G1[cnt1].next = head1[v];    head1[v] = cnt1++;}void add_edge2(int v, int u, int ind){    G2[cnt2].to = u;    G2[cnt2].ind = ind;    G2[cnt2].next = head2[v];    head2[v] = cnt2++;}int ser(int x){    int r = x, i = x, j;    while(r != par[r]) r = par[r];    while(i != r) j = par[i], par[i] = r, i = j;    return r;}void tarjan_lca(int v){    vis[v] = true;    int u;    for(int i = head1[v]; i != -1; i = G1[i].next)        if(!vis[u = G1[i].to])        {            dist[u] = dist[v] + G1[i].cost;            tarjan_lca(u);            par[u] = v;        }    for(int i = head2[v]; i != -1; i = G2[i].next)        if(vis[u = G2[i].to])            res[G2[i].ind] = dist[v] + dist[u] - 2 * dist[ser(u)];}int main(){    int t, a, b, c;    scanf("%d", &t);    while(t--)    {        scanf("%d%d", &n, &m);        init();        for(int i = 0; i < n - 1; i++)        {            scanf("%d%d%d", &a, &b, &c);            add_edge1(a, b, c);            add_edge1(b, a, c);        }        for(int i = 0; i < m; i++)        {            scanf("%d%d", &a, &b);            add_edge2(a, b, i);            add_edge2(b, a, i);        }        dist[1] = 0;        tarjan_lca(1);        for(int i = 0; i < m; i++)            printf("%lld\n", res[i]);    }    return 0;}




0 0