HDU - 2586 How far away? 在線LCA ST算法
阿新 • • 發佈:2018-01-26
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.
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
InputFirst line is a single integer T(T<=10), indicating the number of test cases.
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算法