樹的合併 connect

2021-08-25 08:22:31 字數 1473 閱讀 5930

話說mored經過不懈努力,終於背完了迴圈整數,也終於完成了他的蛋糕大餐。

但是不幸的是,mored得到了詛咒,受到詛咒的原因至今無人知曉。

mored在發覺自己得到詛咒之後,決定去尋找聞名遐邇的術士cd幫忙。

話說cd最近在搞oi,遇到了一道有趣的題目:

給定兩棵樹,則總共有n*m種方案把這兩棵樹通過加一條邊連成一棵樹,那這n*m棵樹的直徑大小之和是多少呢?

cd為了考驗mored是否值得自己費心力為他除去詛咒,於是要他程式設計回答這個問題,但是這mored早就被詛咒搞暈了頭腦,就只好請你幫助他了。

第一行兩個正整數n,m,分別表示兩棵樹的大小。

接下來n-1行,每行兩個正整數ai,bi,表示第一棵樹上的邊。

接下來m-1行,每行兩個正整數ci,di,表示第二棵樹上的邊。

一行乙個整數,表示答案。

4 3

1 22 3

2 41 3

2 3

53
【資料範圍】

對於20%的資料滿足n<=300,m<=300

對於50%的資料滿足n,m<=3000

對於100%的資料滿足n<=10^5,m<=10^5,1<=ai,bi<=n,1<=ci,di<=m

【提示】

樹的直徑指的是樹上的最長簡單路徑。

solution

預處理a[i]表示樹a上以i開頭的最長鏈

同理b[i]表示樹b上以i開頭的最長鏈

f[i]為i向下的最長鏈,dp[i]為向上的最長鏈

那麼f[i]用樹形dp可以求出

考慮求dp[i]

g[i]為i向下的不與最長鏈的共有子節點的最長的鏈

舉例:son[i]為i向下最長鏈的子節點 g[i] 就是除了son[k]外所有子節點向下的最長鏈+1

表述不清。。。

可以自己想想怎麼求a,b

令max表示a樹和b樹的直徑的max

排序統計即可

#include#include#include#include#include#include#define maxn 100005

using namespace std;

int n,m,tot,head[maxn],f[maxn],g[maxn],dp[maxn],t1,t2;

long long a[maxn],b[maxn],sum[maxn],ans,ma;

struct nodee[maxn*2];

void lj(int t1,int t2)

void dfs1(int k,int fa)

else max2=max(max2,f[e[i].v]);}}

if(max==-1e9)f[k]=0,g[k]=-1e9;

else

//cout<>n>>m;

for(int i=1;i=1;i--)

cout<

return 0;

}

樹的合併 connect

話說mored經過不懈努力,終於背完了迴圈整數,也終於完成了他的蛋糕大餐。但是不幸的是,mored得到了詛咒,受到詛咒的原因至今無人知曉。mored在發覺自己得到詛咒之後,決定去尋找聞名遐邇的術士cd幫忙。話說cd最近在搞oi,遇到了一道有趣的題目 給定兩棵樹,則總共有n m種方案把這兩棵樹通過加一...

樹的合併 connect

話說mored經過不懈努力,終於背完了迴圈整數,也終於完成了他的蛋糕大餐。但是不幸的是,mored得到了詛咒,受到詛咒的原因至今無人知曉。mored在發覺自己得到詛咒之後,決定去尋找聞名遐邇的術士cd幫忙。話說cd最近在搞oi,遇到了一道有趣的題目 給定兩棵樹,則總共有n m種方案把這兩棵樹通過加一...

線段樹合併

做永無鄉的時候,以為是主席樹合併,後來感覺不對勁,唔。x和y是兩顆樹的根。這個演算法是從歸併演算法那引申的。實際運作的時候,考慮到了線段樹的本質 線段樹有效節點就是葉子節點。好像是句廢話。其實不是,這句話啟發我們並不需要合併一整棵樹,我們只需要處理好葉子節點,考慮把y樹合併到x上,那麼把y樹的葉子節...