码迷,mamicode.com
首页 > 编程语言 > 详细

HDU - 2586 How far away? 在线LCA ST算法

时间:2018-01-26 22:50:46      阅读:228      评论:0      收藏:0      [点我收藏+]

标签:ati   建立   end   void   number   ace   节点   uniq   after   

There are n houses in the village and some bidirectional roads connecting them. Every day peole always like to ask like this "How far is it if I want to go from house A to house B"? Usually it hard to answer. But luckily int this village the answer is always unique, since the roads are built in the way that there is a unique simple path("simple" means you can‘t visit a place twice) between every two houses. Yout task is to answer all these curious people.

InputFirst line is a single integer T(T<=10), indicating the number of test cases. 
  For each test case,in the first line there are two numbers n(2<=n<=40000) and m (1<=m<=200),the number of houses and the number of queries. The following n-1 lines each consisting three numbers i,j,k, separated bu a single space, meaning that there is a road connecting house i and house j,with length k(0<k<=40000).The houses are labeled from 1 to n. 
  Next m lines each has distinct integers i and j, you areato answer the distance between house i and house j.OutputFor each test case,output m lines. Each line represents the answer of the query. Output a bland line after each test case.Sample Input

2
3 2
1 2 10
3 1 15
1 2
2 3

2 2
1 2 100
1 2
2 1

Sample Output

10
25
100
100

题意:

有 n 个点, n-1条边, 也就是1颗带权树
问:树上点与点之间的最近距离是多少?
有m次查询
给两个点的编号
输出两个点之间的最近距离
做法:
SA算法
将LCA问题转换成RMQ问题
首先需要求三个数组
一个数组是dfs时每个点的访问序列,设这个数组为 dfsf[]
一个数组是每个节点dfs时第一次出现的位置,设这个数组为 first[]
一个数组是每个节点对应的深度,设这个数组为 deep[]
如果询问l,r的最近公共祖先
就是询问在dfsf数组里 first[l]到first[r] 节点 这个区间内的深度最小的节点时哪个节点?
使用ST算法求解这个RMQ问题即可。

代码:
  1 #include<iostream>
  2 using namespace std;
  3 #include<cstdio>
  4 #include<cstring>
  5 #include<vector>
  6 const int maxn = 50000;
  7 struct bian{
  8     int p;
  9     int w;
 10 };
 11 vector<int> dfsf;
 12 vector<bian> maps[maxn];
 13 int fa[maxn];
 14 int v[maxn];
 15 int deep[maxn];
 16 int first[maxn];
 17 template<class T>
 18 class RMQ{
 19     public:
 20      T* a;
 21      int t;
 22      T **mn;
 23      T maxn;
 24      int *log2;
 25      void SetMaxn(T *maxn){
 26         this->maxn=*maxn;
 27      }
 28      void SetMaxn(T maxn){
 29         this->maxn=maxn;
 30      }
 31      void Creat(int maxn){//建立一个最大为maxn的RMQ处理类 
 32           int k=1,p=0;
 33           log2=new int[maxn+10];
 34           for(int i=0;i<=maxn;i++)
 35               log2[i]=(i==0?-1:log2[i>>1]+1);
 36           while(k<maxn){
 37              k*=2;
 38             p+=1;
 39         }
 40         t=p;
 41         mn=new T*[maxn+10];
 42         for(int i=1;i<=maxn;++i){
 43             mn[i] = new T[t+1];
 44             mn[i][0]=dfsf[i-1];
 45         }
 46          for(int j=1;j<=t;++j)
 47              for(int i=1;i+(1<<j) <= maxn;++i){
 48                      T sa=deep[mn[i][j-1]];
 49                     T sb=deep[mn[i+(1<<(j-1))][j-1]];
 50                      if(sa<sb)
 51                          mn[i][j]=mn[i][j-1];
 52                      else
 53                          mn[i][j]=mn[i+(1<<(j-1))][j-1];
 54              }    
 55      }
 56     T Getx(int ql,int qr){
 57             int k=log2[qr-ql+1];
 58             if(deep[mn[ql][k]]<=deep[mn[qr-(1<<k)+1][k]])
 59                 return mn[ql][k];
 60             else
 61                 return mn[qr-(1<<k)+1][k];
 62     }
 63     T Getw(int ql,int qr){
 64             int k=log2[qr-ql+1];
 65             if(deep[mn[ql][k]]<=deep[mn[qr-(1<<k)+1][k]])
 66                 return mn[ql][k];
 67             else
 68                 return mn[qr-(1<<k)+1][k];
 69     }
 70 } ;
 71 RMQ<int> rr;
 72 int n,m;
 73 void dfs(int x,int d){
 74     v[x]=1;
 75     dfsf.push_back(x);
 76     if(first[x]==0)
 77         first[x] = dfsf.size();
 78     deep[x] = d;
 79     for(int i=0;i<maps[x].size();i++){
 80         int point = maps[x][i].p;
 81         if(v[point])
 82             continue;
 83         fa[point]=x;
 84         dfs(point,d+maps[x][i].w);
 85         dfsf.push_back(x);
 86     }
 87 }
 88 void deal(){
 89     scanf("%d%d",&n,&m);
 90     for(int i=0;i<=n;i++)
 91         maps[i].clear();
 92     memset(v,0,sizeof(v));
 93     memset(fa,0,sizeof(fa));
 94     memset(first,0,sizeof(first));
 95     dfsf.clear();
 96     for(int i=0;i<n-1;i++){
 97         int l,r,w;
 98         scanf("%d%d%d",&l,&r,&w);
 99         bian pt;
100         pt.p=r;pt.w=w;
101         maps[l].push_back(pt);
102         pt.p=l;
103         maps[r].push_back(pt);
104     }
105     dfs(1,0);
106     rr.Creat(dfsf.size());
107     int l,r,dl,dr;
108     for(int i=0;i<m;i++){
109         scanf("%d%d",&l,&r);
110         int ll,rrr;
111         ll=first[l],rrr=first[r];
112         //cout<<"first: "<<ll<<" "<<rrr<<endl;
113         if(ll>rrr)
114             swap(ll,rrr);
115         int k=rr.Getw(ll,rrr);
116         int ans=0;
117         ans+=deep[k]-deep[l];
118         ans+=deep[k]-deep[r];
119     //    cout<<"root "<<k<<endl;
120         if(ans<0)
121             ans=0 - ans;
122         printf("%d\n",ans);
123     }
124 }
125 int main(){
126     int t;
127     scanf("%d",&t);
128     while(t--)
129         deal();
130     return 0;
131 }

 

HDU - 2586 How far away? 在线LCA ST算法

标签:ati   建立   end   void   number   ace   节点   uniq   after   

原文地址:https://www.cnblogs.com/xfww/p/8361489.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!