1. 程式人生 > >HDU - 2586 How far away? 在線LCA ST算法

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

ole poi cto st算法 求解 style after nsis return

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算法