傳送門
今天終於找到了一種比較方便好懂的用lct維護生成樹的辦法。
以前用\(mrclr\)的方法……不是很理解,然後我寫在這道題的時候還錯了……
首先先看一下這道題。這很明顯就是讓我們動態的維護乙個最小生成樹。不過因為刪邊的過程很難維護,所以我們改成先把邊存起來,之後倒序回加。
一開始我們先用lct模擬kruskal,之後如果遇到乙個環,那麼我們就找到當前路徑上邊權最大的邊與加入的邊進行比較即可。
查詢的時候提取路徑並輸出答案。
至於維護,我們可以把邊看成乙個點,之後把這條邊所連線的兩個點分別與它連邊,切開的時候也是這樣。對於維護最大值所在的位置,我們在pushup的時候,分別用左右兒子的pos更新即可。
**寫的比較醜……比較長……我是用鄰接矩陣存的兩點之間邊的編號(因為資料範圍小),也可以使用pair或者map。
#include#include#include#include#include#include#define b puts("oops");
#define rep(i,a,n) for(int i = a;i <= n;i++)
#define per(i,n,a) for(int i = n;i >= a;i--)
#define enter putchar('\n')
#define pr pair#define mp make_pair
#define fi first
#define sc second
using namespace std;
typedef long long ll;
const int m = 200005;
const int n = 10000005;
int read()
while(ch >='0' && ch <= '9') ans = ans * 10 + ch - '0',ch = getchar();
return ans * op;
}int n,m,k,head[m],ecnt,sta[m],top,q,x,y,g[1005][1005],ans[m],cnt;
bool vis[m<<1];
struct ask
a[m<<1];
struct edge
}e[m<<1];
struct tree
t[m<<2];
bool nroot(int x)
bool get(int x)
void rever(int x)
void pushup(int x)
void pushdown(int x)
void rotate(int x)
void splay(int x)
}void access(int x)
void makeroot(int x)
int findroot(int x)
void split(int x,int y)
void link(int x,int y)
void cut(int x,int y)
int main()
int tot = 0,cur = 0;
while(tot < n-1)
per(i,q,1)
}per(i,cnt,1) printf("%d\n",ans[i]);
return 0;
}
題解 WC2006 水管局長
感覺這題好強啊 本來以為能過,結果毫無疑問的被ge了一頓 在這裡記錄一下做的過程,也免得以後又忘記啦。首先,我們應看出在這張圖上,要讓經過的水管最長的最短,就是要維護一棵動態的最小生成樹。只是刪除邊不是很好操作,所以我們將刪邊改為加邊,反向處理。如果發現新加的邊可以更新最小生成樹,我們就應該更新圖,...
WC2006 水管局長資料加強版
sc省my市有著龐大的地下水管網路,嘟嘟是my市的水管局長 就是管水管的啦 嘟嘟作為水管局長的工作就是 每天供水公司可能要將一定量的水從x處送往y處,嘟嘟需要為供水公司找到一條從a至b的水管的路徑,接著通過資訊化的控制中心通知路徑上的水管進入準備送水狀態,等到路徑上每一條水管都準備好了,供水公司就可...
WC2006 水管局長 LCT維護最小生成樹
貌似要省選了?似乎不關我這個蒟蒻的事,還是給oiers們加油吧!第一次學到了邊轉換為點的神奇操作。luogu傳送門 由於要找路徑上的最小的最長度 很繞自理解 還是很容易就想到最小生成樹的。再由於想到維護最小生成樹的時候刪邊還是很複雜的就想到這道題的刪邊離線倒著來做,將刪邊轉換成加邊來做就吼了。但是權...