【Lca 線上st演算法】hdu 2586 How far away ?
LCA 線上st演算法
題意: 對於一個圖,n(<=40000)個點,給出n-1條邊(u,v,w,), m(<=200)個詢問給出兩點,問其最短距離
題解: LCA問題(求最近公共祖先問題),線上演算法(對於每個詢問得出答案,相對離線演算法需要得到所有詢問後一次性給出答案)。
以任意一點作為根節點,兩點最短距離為,兩點分別到根節點的距離和減去兩倍的最近公共祖先到根節點的距離。
st演算法: 基於RMQ(dp)的演算法;
dfs預先處理出ver[] (向下遞迴和回溯經過的點),dep[] (同上經過點的深度),first[] (對於ver,點第一次出現在ver[]陣列的位置)。
分別介紹它們的作用:
first[] 可以對於給出的點得到在dep[]上的範圍,[思考dp的過程]這個範圍肯定包含了其同棵樹的根節點(即最近公共祖先)
dep[] 在得到的範圍裡用RMQ尋找裡面最小值的位置(即公共祖先的位置)
ver[] 對於得到的位置只是dep[]陣列上的位置,ver[]是相對位置上對應的點
注意: 1.每個節點可能遍歷兩邊,dep,ver陣列開N*2
2. first[]點在dep[]對應的id,(l,r)誰大誰小還不確定的
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
//#pragma comment(linker, "/STACK:102400000,102400000")
const double PI = acos(-1.0);
const double eps = 1e-6;
const int INF=0x3f3f3f3f;
const LL mod = 1e9+7;
const int N = 100000+10;
const int M = 2500000;
struct Node
{
int to;
int val;
};
vector<Node> ma[N]; //vector 記錄圖
int dir[N],ver[N],first[N],dep[N];
bool vis[N];
int top;
void dfs(int n,int depth,int dist) //dfs處理需要陣列
{
vis[n]=true;
ver[++top]=n; first[n]=top; dep[top]=depth; dir[n]=dist;
for(int i = 0; i < ma[n].size(); i++){
Node temp = ma[n][i];
if(!vis[temp.to]){
dfs(temp.to,depth+1,dist+temp.val);
ver[++top]=n; dep[top]=depth; //這倆陣列回溯時也需要記錄
}
}
}
int dp[N][30]; //代表區間(i,i+(1<<j)-1)的最小值的位置
void ST(int l,int r) //預處理RMQ的dp陣列
{
for(int i = l; i <= r; i++)
dp[i][0]=i;
for(int i = 1; (1<<i) <= r-l+1; i++){
for(int j = l; j+(1<<i)-1 <= r; j++){
int x = dp[j][i-1];
int y = dp[j+(1<<(i-1))][i-1];
dp[j][i] = dep[x]<dep[y]?x:y;
}
}
}
int RMQ(int l,int r) //RMQ處理出(l,r)的最小值位置
{
int k = 0;
while((1<<(k+1)) <= r-l+1)
k++;
int x = dp[l][k];
int y = dp[r-(1<<k)+1][k];
return dep[x]<dep[y]?x:y;
}
int LCA(int x,int y) //將處理出的位置對應其點
{
int l = first[x];
int r = first[y];
if(l > r){int temp = l; l = r; r = temp;} //(l,r)誰大誰小還不確定的
int id=RMQ(l,r);
return ver[id];
}
int main()
{
int T;
scanf("%d",&T);
while(T--){
int n,m;
scanf("%d%d",&n,&m);
for(int i = 1; i <= n; i++)
ma[i].clear();
for(int i = 1; i < n; i++){
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
Node temp;
temp.to = v; temp.val = w;
ma[u].push_back(temp);
temp.to = u; temp.val = w;
ma[v].push_back(temp);
}
memset(vis,0,sizeof(vis));
top = 0;
dfs(1,0,0);
ST(1,top);
while(m--){
int u,v;
scanf("%d%d",&u,&v);
int lca = LCA(u,v);
printf("%d\n",dir[u]+dir[v]-2*dir[lca]);
}
}
return 0;
}
相關文章
- 【Lca 離線Tarjan演算法】hdu 2586 How far away ?演算法
- LCA最近公共祖先 線上演算法和離線演算法 模板演算法
- ST演算法演算法
- Lca相關演算法演算法
- HDU1213-How Many Tables
- 演算法總結--ST表演算法
- HDU 1213 How Many Tables(並查集)並查集
- lca
- HDU 2157 How many ways?? (矩陣快速冪)矩陣
- 動態規劃 hdu 1978 How many ways動態規劃
- 演算法學習筆記(3.1): ST演算法演算法筆記
- 求 LCA
- 演算法學習筆記(5): 最近公共祖先(LCA)演算法筆記
- HDU 3038 How Many Answers Are Wrong (帶權並查集)並查集
- Oracle Far Sync例項Oracle
- RMQ求lcaMQ
- 樹上問題/簡單演算法 LCA【最近公共祖先】演算法
- 5 Using Far Sync Instances 使用Far Sync遠端同步例項
- HDU 4123 Bob's Race:樹的直徑 + 單調佇列 + st表佇列
- MySQL server has gone awayMySqlServerGo
- st
- 倍增與ST演算法 --演算法競賽專題解析(28)演算法
- POJ 1330 LCA最近公共祖先 離線tarjan演算法演算法
- DFN 序求 LCA
- LCA + 樹上倍增
- LCA(倍增與Tarjan)
- Why LA let Ariza go awayGo
- ST表
- LCA學習筆記筆記
- 樹上公共祖先(LCA)
- 問題MySQL server has gone awayMySqlServerGo
- Python演算法-How to sort a dictionary by valuePython演算法
- 4.12 st_size、st_blksize和st_blocks成員-檔案尺寸BloC
- POJ 3264-Balanced Lineup(RMQ-ST演算法)MQ演算法
- HDU5972Regular Number(ShiftAnd演算法 bitset)演算法
- 淺談倍增法求解LCA
- MySQL server has gone away 解決方案MySqlServerGo
- Oracle 12c DG新特性Far SyncOracle