bzoj 那個是加強版
lct 維護動態最小瓶頸樹
題意:給乙個圖,每次詢問兩個點之間路徑的最大值的最小值,或斷開乙個邊,始終保證圖連通
用 lct 維護,發現斷邊不怎麼好做,所以離線下來倒序處理,常規套路
就是先跑乙個最小瓶頸生成樹,然後每次加邊,如果加的這個邊的邊權大於它兩個端點間原來路徑的最大值,就不管他,否則,把兩端點原來路徑上權值最大的邊斷開,把新邊加進去
在實現操作前,要先清楚 lct 如何維護邊的資訊,其實可以為每乙個邊新建乙個虛擬節點,權值為邊權,其它的真實節點點權都是零
然後每次讓兩個點相連,就是讓它們分別與連的這個邊對應的虛擬節點相連就行了
然後兩種操作只要都先 split 出來然後處理就行了
為了方便知道哪個路徑上的邊是邊權最大的,lct 節點中的 max 儲存的實際上是最大邊權的邊的編號
由於 \(n\) 比較小(普通版),所以一開始建 lct 之前的操作怎麼亂搞都行,不過我這樣寫就過不了加強版了,那個加強版又是卡時又是卡空間的懶得寫了
#include#include#include#include#include#include#include#define reg register
#define en std::puts("")
#define ll long long
inline int read()
while(c>='0'&&c<='9')
return y?x:-x;
}#define n 1005
#define m 100005
int n,m,q;
int allu[m],allv[m],allw[m];
int id[n][n],map[n][n];
struct dataedge[m];
int tot;
int k[m],u[m],v[m],ans[m];
struct tr*null,*pos[n+m],dizhi[n+m];
//1 - n 實際點
//n+1 - n+m 代表邊
#define pushup(tree) (tree->max=max(max(tree->son[0]->max,tree->son[1]->max),tree->val))
#define ident(tree,fa) (fa->son[1]==tree)
#define notroot(tree) (tree->fa->son[0]==tree||tree->fa->son[1]==tree)
inline int max(int x,int y)
inline void connect(tr *tree,tr *fa,int k)
inline void pushdown(tr *tree)
inline void rotate(tr *tree)
inline void splay(reg tr *tree)
}inline void access(tr *x)
}inline void makeroot(tr *tree)
inline void split(tr *x,tr *y)
inline void link(tr *x,tr *y)
inline void cut(tr *x,tr *y)
inline void init()
for(reg int i=n+1;i<=n+m;i++)
}inline int cmp(data a,data b)
else
} }for(reg int i=1;i<=q;i++)if(k[i]==1) printf("%d\n",ans[i]);
return 0;
}
P4172 WC2006 水管局長
題目鏈結 題目背景 sc 省 my 市有著龐大的地下水管網路,嘟嘟是 my 市的水管局長 就是管水管的啦 題目描述 每天供水公司可能要將一定量的水從 u uu 處送往 v vv 處,嘟嘟需要為供水公司找到一條從 u uu 至 v vv 的水管的路徑,接著通過資訊化的控制中心通知路徑上的水管進入準備送...
P4172 WC2006 水管局長
傳送門 顯然 lct 動態維護最小生成樹 詢問就是問樹上兩點的路徑中權值最大的邊 為了維護邊權,我們要把邊也看成點,為了方便,邊在 lct 中的編號為 n 1 到 n m 因為正做不好維護刪邊,所以離線倒過來,變成加邊 在反過來做的時候,為了維護最小生成樹要知道哪些邊被刪除了 用 set 或者 ma...
洛谷P4172 WC2006 水管局長
lct動態維護最小生成樹的典例 這個都是套路,倒序處理,將刪邊變成加邊 再將邊換成點,然後就可以做到點權維護邊權資訊 說一下加邊的過程大概是 一 首先最小生成樹,保證初始最優 二 對於新加入的一條邊,找出原x y鏈上的最大邊,替換 第二點的實現比較有意思 因為是在樹上加邊,所以一定會形成乙個環,那麼...