bzoj 1787 Meet 緊急集合

2022-05-01 01:03:10 字數 1289 閱讀 2382

給出bzoj鏈結。

這個題還是求最近公共祖先的問題。

而該題不同於別的題,它是需要求三個點的最近公共祖先。

我們就需要求出三個點兩兩之間的lca。

而這三個lca之間,必有兩個是相同的。

如果兩個點相同,那另一點就是那三個點的lca。

如果三個點都相同,那麼該點就是那三個點的lca。

最後還需要統計走過的邊的長度。

三個點都相同的情況很好搞,就是計算三個點與那個lca的深度差,加起來就是答案。

但是兩個點就難一點。如果lca_a_b與lca_a_c相同,就需要求出lca_b_c到a,b,c的長度,就可以轉化成b,c到它們的最近公共祖先lca_b_c的長度,和lca_b_c,a到它們的最近公共祖先lca_a_b(或lca_a_c)的長度。

那麼就先求出lca_b_c與b和c的深度差,再求出lca_a_b(或lca_a_c)與lca_b_c和a的深度差,加起來就是結果。

**:

1 #include2 #include3 #include4

#define n 500010

5#define m 1000010

6using

namespace

std;

7int

next[m],to[m],head[n],num,size[n],deep[n],father[n],top[n],n,m,a,b,c,c1,c2,c3,ans;

8void add(int false_from,int

false_to)

13void dfs1(int

x)22}23

void dfs2(int

x)34

for(int i=head[x];i;i=next[i])

35if(father[x]!=to[i]&&to[i]!=mmax)

36dfs2(to[i]);37}

38int lca(int x,int

y)44

if(deep[x]return

x;45

return

y;46}47

intmain()

54 dfs1(1

);55 dfs2(1

);56

for(int i=1;i<=m;++i)

66else

67if(c1==c2)

72else

73if(c1==c3)

78else

83}84return0;

85 }

view code

bzoj1787 緊急集合

對於三個點x y和 z,設a lca x,y b lca x,z 不妨假設a的深度比 b大,則b是 a的祖先 因為a是 x的祖先,b也是 x的祖先 首先將集合點定在a,考慮 a向每乙個方向調整,a向父親調整會讓x和 y答案加一,a向靠近 x y同理 的兒子調整,會讓y和 z答案加一,向其他兒子調整,...

BZOJ3438 小M的作物

bzoj3438 小m的作物 小m在mc裡開闢了兩塊巨大的耕地a和b 你可以認為容量是無窮 現在,小p有n中作物的種子,每種作物的種子有1個 就是可以種一棵作物 用1.n編號 現在,第i種作物種植在a中種植可以獲得ai的收益,在b中種植可以獲得bi的收益,而且,現在還有這麼一種神奇的現象,就是某些作...

bzoj3438 小M的作物

題目鏈結 先考慮沒有額外收益的時候怎麼做。從 s 向第 i 點連一條容量為 a i 邊,表示種在 a 中的收益。從第 i 個點向 t 連一條容量為 b i 的邊,表示種在 b 中的收益。然後求出來最小割,用總收益減去即可。完成之後如下圖 然後考慮如何處理額外收益 對於每乙個額外的收益,我們先新建乙個...