bzoj 4242 水壺 最小生成樹 樹上倍增

2021-07-10 18:35:03 字數 1211 閱讀 4883

為了降低ac率

這道題目我各種花樣作死爆oj,最後還是和標算改得差不多了。。。

顯然答案應該為建築物構成的最小生成樹中,兩點間的最大路徑;那麼只要得到這棵最小生成樹就可以用倍增在o(qlogn)的時間內得到答案了。因此關鍵是求最小生成樹。

注意到是平面圖,因此考慮用bfs求最小生成樹。直接以每個建築為原點拓展顯然不行,那麼我們可以把每個建築都加入佇列一起拓展,那麼對於乙個點,一定會被其中的乙個建築第一次拓展到,則令這個點為該建築的「勢力範圍」。那麼對於兩個建築「勢力範圍」邊界上接觸的點,顯然這兩個建築之間的邊只能有邊界上的點得到。因此就用這些點連邊即可。顯然這樣得到是最小生成樹。

然後用倍增求lca的方法得到答案即可。

ac**如下:

#include#include#include#define n 2005

#define m 200005

using namespace std;

int n,m,pt,cas,tot,cnt,fa[m][18],g[m][18],bin[25],anc[m],fst[m],pnt[n*n],nxt[n*n],len[n*n];

int dep[m],h[n*n][2],d[n][n],blg[n][n]; bool mp[n][n];

const int dx[4]=,dy[4]=;

int read()

return x;

}struct grapg

}g1,g2;

int getanc(int x)

void dfs(int x)

for (p=g2.fst[x]; p; p=nxt[p]) }}

int qry(int x,int y)

if (x!=y) ans=max(ans,max(g[x][0],g[y][0])); return ans;

}int main()

int head=0,tail=0,x,y,z;

memset(d,-1,sizeof(d));

for (i=1; i<=pt; i++)

while (head0 && u<=m && v>0 && v<=n && mp[u][v])

if (d[u][v]==-1) else if (z!=blg[u][v]) g1.add(d[u][v]+d[x][y],z,blg[u][v]);

} }for (i=0; i

by lych

2016.3.26

題目 BZOJ 4242 水壺

題目大意 某市是乙個被分成h w h times w h w塊區域的長方形,每個區域都是建築物 原野 牆壁之一。建築物的區域有p pp個,編號為1 p 1 dots p 1 p。只有建築物和原野能夠進入,而且每次只能走到相鄰的區域中,且不能移動到市外。現在需要在各個建築物之間往返。在原野上每走過乙個...

bzoj 2561 最小生成樹

給定乙個邊帶正權的連通無向圖g v,e 其中n v m e n個點從1到n依次編號,給定三個正整數u,v,和l u v 假設現在加入一條邊權為l的邊 u,v 那麼需要刪掉最少多少條邊,才能夠使得這條邊既可能出現在最小生成樹上,也可能出現在最大生成樹上?第一行包含用空格隔開的兩個整數,分別為n和m 接...

bzoj2561 最小生成樹

time limit 10 sec memory limit 128 mb submit 1024 solved 520 submit status discuss 給定乙個邊帶正權的連通無向圖g v,e 其中n v m e n個點從1到n依次編號,給定三個正整數u,v,和l u v 假設現在加入一...