屠龍者(最大子樹)

2021-10-02 23:16:37 字數 1546 閱讀 9126

小明是a村里的屠龍者,他一直保衛著村子的和平,以不受惡龍的侵擾。而惡龍們也對小明恨之入骨,於是惡龍們決定組織一次集體進攻,以打敗小明,拿下a村。小明知道,惡龍集體進攻的時候,會在彼此之間建立一種神秘的鏈結,而被這種鏈結連線起來的惡龍能夠增長彼此的能力,且每有乙隻惡龍加入到乙個鏈結中,這個鏈結裡的所有龍的能力都會加1,而只有當小明的戰鬥力大於龍的戰鬥力時,才能將龍殺死。萬幸的是,小明有一把一次性的屠龍刀,他可以無視戰鬥力地殺死乙隻龍,並消除這條龍身上的所有鏈結。假設每條龍不被鏈結時的戰鬥力為1,初始時所有n只惡龍被n-1條鏈結連線在一起。小明想知道他至少要有多少的戰鬥力,才能將所有龍都殺死,同時他想知道,他應該用屠龍刀殺掉哪隻龍。

輸入的第一行是乙個整數n(1<=n<=40000), 表示一共有n隻龍。接下來n-1行整數對a,b(以空格分隔),表示龍之間的鏈結關係。

輸出以空格分隔的兩個整數。第乙個整數x,表示應用屠龍刀殺死的龍的編號。若有多隻龍都可被屠龍刀殺死,輸出編號最小的那個第二個整數t,表示小明至少需要有的戰鬥力。輸入8

1 22 3

1 55 6

6 82 4

5 7輸出

1 5模擬給出的示例,當殺死某條龍,也就是刪除某乙個節點之後,那麼剩下的節點按照被殺死的節點的鄰節點分成了幾個集合,那麼最大的集合(節點數最多)的節點數加1,就是屠龍者至少要擁有的能力。所以本質上要求所有節點的所有子樹中最大的那個子樹。

如果是遍歷某乙個節點,分別求出最大子樹,由於存在大量的冗餘計算,一定會超時。由於題目中明確初始n個節點通過n-1條邊鏈結在一起,所以初始就可以看作一棵樹,自己指定乙個根節點之後(相當於給出了方向,將無向圖變成了有向圖),就可以深搜求出每乙個節點作為根節點的子樹所包含的節點數量(所有子樹大小和+1),因為加上了方向性,還有乙個子樹沒有辦法直接求出,用總的節點數-該節點作為根節點的子樹的大小,就是剩下的那個子樹的大小,在這個過程中在維持乙個最小的最大子樹記錄就可以了。

#include

#include

#define nn 40010

using

namespace std;

vectorint>

>

long

(nn,vector<

int>()

);int n,maxn=nn,index_max=nn;

intgettreesum

(int index,

int pre)

sum++

;int left=maxv;

if(n-sum>maxv)

left=n-sum;

if(maxn>left)

else

if(maxn==left&&index_max>index)

index_max=index;

return sum;

}int

main()

gettreesum(1

,-1)

;if(maxn!=0)

maxn++

; cout<" "

}

最初所有節點鏈結在一起這個條件將複雜度降低了,否則需要兩次深搜。

尋找最大子樹

問題描述 給乙個二叉樹,每個節點都是正或負整數,如何找到乙個子樹,它所有節點的和最大?思路 採用自底向上的計算。先計算左右子樹總和值,用左右子樹的總和加上當前節點值,如果當前總和大於最大值,則更新最大值,同時將最大子樹根節點更新為當前根。簡單說,就是後序遍歷。include include usin...

最大子樹和

題目描述 小明對數學飽有興趣,並且是個勤奮好學的學生,總是在課後留在教室向老師請教一些問題。一天他早晨騎車去上課,路上見到乙個老伯正在修剪花花草草,頓時想到了乙個有關修剪花卉的問題。於是當日課後,小明就向老師提出了這個問題 一株奇怪的花卉,上面共連有n 朵花,共有n 1條枝幹將花兒連在一起,並且未修...

緊急疏散(最大子樹)

體育場突然著火了,現場需要緊急疏散,但是過道真的是太窄了,同時只能容許乙個人通過。現在知道了體育場的所有座位分布,座位分布圖是一棵樹,已知每個座位上都坐了乙個人,安全出口在樹的根部,也就是1號結點的位置上。其他節點上的人每秒都能向樹根部前進乙個結點,但是除了安全出口以外,沒有任何乙個結點可以同時容納...