給出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 #include4view code#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 }
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 中的收益。然後求出來最小割,用總收益減去即可。完成之後如下圖 然後考慮如何處理額外收益 對於每乙個額外的收益,我們先新建乙個...