1. 程式人生 > 其它 >MySQL 學習筆記3——增刪改查、連表

MySQL 學習筆記3——增刪改查、連表

倍增求LCA

\(f_{x,k}\) 表示 \(x\) 向根節點走了 \(2^k\) 步到達的節點。
易得:

\[f_{x,k+1}=f_{f_{x,k},k} \]

所以遍歷一次圖可預處理出。
對於一組 \((x,y)\) 的詢問:

  1. 選擇深度更深的節點,倍增跳到與另一點深度相同處。
  2. 若此時兩點相同,則得出答案。
  3. 否則 \(x,y\) 在不重合的前提下一隻向上倍增。
  4. 最後 \(x\)\(y\) 的父親一定是 LCA。
inline void bfs(){
    t=(int)log(n)/log(2)+1;
    q.push(root);d[1]=1;
    while(q.size()){
        int x=q.front();q.pop();
        for(int i=head[x];i;i=nxt[i]){
            int y=ver[i];
            if(d[y])continue;
            d[y]=d[x]+1,f[y][x]=0,q.push(y);
            for(int j=1;j<=t;j++)f[y][j]=f[f[y][j-1]][j-1];
            q.push(y);
        }
    }
}
inline int Lca(int x,int y){
    if(dep[x]<dep[y])swap(x,y);
    for(int i=t;i>=0;i--)
        if(dep[f[x][i]]>=dep[y])x=fa[x][i];
    if(x==y)return x;
    for(int i=t;i>=0;i--)
        if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i];
    return f[x][0];
}

P4180 [BJWC2010]嚴格次小生成樹
容易得到,嚴格次小生成樹一定是最小生成樹替換一條邊得到的。
先求出最小生成樹,考慮加入未在最小生成樹內的邊 \((x,y,z)\),那麼樹上 \(x\)\(y\) 的路徑上一定有一條邊被替換。
\(x\)\(y\) 的路徑上最小邊權為 \(z_1\),嚴格次小邊權為 \(z_2\), 那麼:

  1. \(z\ne z_1\) 時,替換 \((x,y,z)\) 得到的嚴格次小生成樹一定換去 \(z_1\) 這條邊。
  2. 否則換去 \(z_2\) 這條邊。

用樹上倍增求出 \(z_1\)\(z_2\),此過程和求 LCA 相似。

P4281 [AHOI2008]緊急集合 / 聚會


建議畫圖理解。
引理1:三個點的兩兩 LCA 必有一對重合。
反證法易證。
引理2:答案一定是另一個 LCA。
如果選另一個LCA,兩個 LCA 中間的邊被經過1次,否則被經過2次。

P1852 跳跳棋

由於一種狀態想要縮小隻有一種方案,所以可以把縮小的方案建成一棵樹,答案就是起始和結束狀態的 LCA。
考慮不暴力縮小,而是一次把一邊縮小到比另一邊小。
最後二分距離 LCA 的距離後倍增即可。