HDU 2586

一道很经典的lca入门题。写完收获颇多。
链接:http://acm.hdu.edu.cn/showproblem.php?pid=2586
分析:写这道题首先要懂得一种rmq算法,我用的是st算法,我想线段树应该也可以吧。然后还要知道lca是什么东东(废话了==)。有几个工作要做。 1:建图,我用的指针链表。 2:dfs构造数组。 3:用st算法求值。
4:回收内存(如果用链式前向星就不需要了,我的代码也没回收,结果就是很吃内存)。

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cmath>
using namespace std;
const int N = 400000+10;
struct edge
{
    int to,value;
    edge *next;
};
struct tu
{
    edge *next;
};
tu dian[N];
int first[N],len[N],du[N>>1],book[N],tail;
int f[N>>1][25];
void Addedge(int a,int b,int v);
int dfs(int t,int dis);
void MakeRmq(int n);
int Anwer(int s,int v);
int main()
{
  int t,i,j,n,m,a,b,v;
  scanf("%d",&t);
  while(t--)
  {
      scanf("%d%d",&n,&m);
      for(i=1; i<=n; i++)
        dian[i].next = NULL;
      memset(du,0,sizeof(du));
      memset(len,0,sizeof(len));
      memset(book,0,sizeof(book));
      memset(first,0,sizeof(first));
      for(i=1; i<n; i++)
      {
         scanf("%d%d%d",&a,&b,&v);
         Addedge(a,b,v);
         Addedge(b,a,v);
      }
      tail = 0;
      dfs(1,0);
      MakeRmq(tail);
      while(m--)
      {
          scanf("%d%d",&a,&b);
          int ans1 = Anwer(first[a],first[b]);
          printf("%d\n",len[a]+len[b]-2*ans1);
      }
  }
  system("pause");
  return 0;

}
void Addedge(int a,int b,int v) //建图
{
    edge *l = new(edge);
    l->to = b;
    l->value = v;
    l->next = dian[a].next;
    dian[a].next = l;
}
int dfs(int t,int dis)
{
    if(!book[t])
    {
        du[++tail] = t;
        book[t] = 1;
        len[t] = dis;
        first[t] = tail;
    }
    edge *l = dian[t].next;
    while(l != NULL)
    {
        if(!book[l->to])
        {
            dfs(l->to,dis+l->value);
            du[++tail] = t;
        }

        l = l->next;
    }

}
void MakeRmq(int n)
{
    int i,j;
    for(i=1; i<=n; i++)
    {
        f[i][0] = len[du[i]];
    }



    for(j=1; (1<<j) < n; j++)
      for(i=1; i+(1<<(j))<=n; i++)
      {
          f[i][j] = min(f[i][j-1] , f[i+(1<<(j-1))][j-1]);
      }
}
int Anwer(int s,int v)
{
    if(s > v)
    {
        int t = s;
        s = v;
        v = t;
    }
    int m = log2(v-s+1);
    return min(f[s][m],f[v-(1<<m)+1][m]);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值