HDU

来源:互联网 发布:淘宝宝贝图片怎么上传 编辑:程序博客网 时间:2024/06/06 11:02

HDU-2586 HDU - 2586 


思路:还是求lca,只不过这次要学习新方法,所以用了倍增

惯例推荐博客:倍增

讲的特别好~

#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>using namespace std;const int maxn = 1e5;int n,m;struct node{    int to,w,next;    node(){}    node(int a,int b,int c){to = a; w = b ; next = c;}}edge[maxn];int edgenum = 0;int h[maxn] , dp[maxn][21], maxd[maxn] , vis[maxn], dis[maxn];void init(){    for(int i = 0; i <= n ; i++)        h[i] = -1,  dp[i][0] = i, maxd[i] = 0;    edgenum = 0;}void add(int f,int t,int w){    edge[edgenum] = node(t,w,h[f]);    h[f] = edgenum ++ ;}void pre(int u,int d)       //处理每个结点的深度和父亲{    for(int i = h[u]; ~i; i = edge[i].next)    {        int v = edge[i].to, w = edge[i].w;        if(!vis[v])        {            dis[v] = dis[u] + w;            dp[v][0] = u;   maxd[v] = d;            vis[v] = 1; pre(v,d+1);            vis[v] = 0;        }    }}int doubl()                 //倍增的预处理{    for(int j = 1; j <= 20; j++)    for(int i = 1; i <= n ; i++)    {        if((1 << j) > maxd[i]) continue;        int k = dp[i][j-1]; dp[i][j] = dp[k][j-1];    }    return 0;}int query(int a,int b){    int x = a, y = b;    int ans = 0;    if(maxd[x] > maxd[y]) swap(x,y);    for(int j = 20; j >= 0; j--)    {        if(maxd[x] == maxd[y]) break;        if(maxd[y] - (1<<j) < maxd[x]) continue;        ans += (dis[y] - dis[dp[y][j]]);        y = dp[y][j];    }    if(x == y) return ans;    for(int j = 20; j >= 0; j--)    {        if(dp[x][0] == dp[y][0] )break;        if(maxd[y] - (1 << j) < 0 || dp[x][j] == dp[y][j]) continue;        ans += (dis[x]-dis[dp[x][j]] + dis[y] - dis[dp[y][j]]);        x = dp[x][j], y = dp[y][j];    }    ans += (dis[x] - dis[dp[x][0]] + dis[y] - dis[dp[y][0]]);    return ans;}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(a,b,c); add(b,a,c);        }        vis[1] = 1, maxd[1] = 0, pre(1,1);  vis[1] = 0;        doubl();        for(int i = 0; i < m ; i++)        {            scanf("%d%d",&a,&b);            printf("%d\n",query(a,b));        }    }    return 0;}