ACM模板 學習筆記 樹相關

2021-10-19 12:11:09 字數 3454 閱讀 9391

持續更新中qwq 咕咕咕

此次update是在我原先自己的部落格的基礎上進行更新的(隔了兩年該忘的不該忘的都忘完了qwq),順便整理一下我的acm模板qaq

(我保證2021.3.1開學之前搞完!)

從包含的n個點的空圖開始,依次加入m條帶權邊。每加入一條邊,輸出當前圖中最小生成樹權值(如果當前圖不聯通,輸出無解)。

如果加入一條邊(u,v)後,圖中恰好包含乙個環,根據迴路性質,刪除該葫蘆上權值最大的邊即可,因此只需要在加邊之前的mst中找到u到v唯一路徑上權值最大的邊,再和e比較,刪除權值較大的一條。由於路徑唯一,可以用dfs或者bfs找到這條u到v的路徑,總時間複雜度為o(n

m)

o(nm)

o(nm)。

給出加權無向圖,求乙個最小生成樹,使得最大邊權值盡量小。

每顆最小生成樹一定是最小瓶頸生成樹,每顆最小瓶頸生成樹卻不一定是最小生成樹

給定加權無向圖的兩個結點u和v,求出從u到v的一條路徑,使得路徑上的最長邊盡量短。

我們直接求出這個圖的最小生成樹,則起點和終點在書上的唯一路徑就是我們要找的路徑,這條路經上的最長邊就是問題的答案。

給出加權無向圖,求每兩個結點u和v之間的最小瓶頸路的最大邊長f(u

,v

)f(u,v)

f(u,v)

我們先求出來最小生成樹,同時計算f(u

,v

)f(u,v)

f(u,v)

,每訪問乙個結點u時,考慮所有已經訪問過的老結點x,更新f(x

,u)=

max(

f(x,

v),w

(u,v

))

f(x,u)=max(f(x,v),w(u,v))

f(x,u)

=max

(f(x

,v),

w(u,

v)),其中v是u的父親結點。(使用dfs實現上述過程)

樹上一點,滿足刪除該點時,樹內剩下的子樹最大節點數最小。

inline

void

solve

(int x,

int f)

maxx[x]

=max

(maxx[x]

, n - siz[x]);

return

;}

之後遍歷一遍,maxx最小的就是樹的重心。

樹(可帶權)上最長的簡單路徑。

inline

voiddp(

int x)

}

從根節點開始dfs遍歷樹——在點x時,走到乙個未遍歷過的兒子,或者兒子已經全部遍歷過從x返回到父親時,以此法得到的遍歷序列是尤拉序。

從根節點開始dfs遍歷樹,乙個節點第一次被遍歷到時加入到序列中,以此法得到的遍歷序列是dfs序。

從根節點開始dfs遍歷樹,乙個節點第一次被遍歷或者遍歷完兒子要退出時將其加入到序列中,以此法得到的遍歷序列是括號序。

1、將樹中子樹表示為遍歷序列的一段區間。(括號序)

2、判斷乙個點是否在以另外乙個點為根的子樹裡。

(設乙個點x在dfs序列中位置為dfn(x),那麼如果點y在以x為根的子樹離=>dfn

(x)≤

dfn(

y)

n(x)

+siz

e(x)

dfn(x)\le dfn(y)df

n(x)

≤dfn

(y)n(x)

+siz

e(x)

3、和2等價的,還可以推出判斷點x是否在點y到根節點的路徑上(只要判斷不在子樹里就可以了)rr

xarr_x

arrx

​插入權值,從位置lea

xlea_x

leax

​插入權值的相反數,做一次字首和後,設sum

isum_i

sumi

​為前i項的和,顯然點x到根節點的路徑權值就是sum

arrx

sum_

sumarr

x​​維護這個可以修改的字首和陣列可以用樹狀陣列qwq

我們定義葉子結點為度數為1的節點。

每次尋找乙個最小的葉子結點,把與它相連的點放入prufer序列裡,然後從樹上刪掉這個點以及它相連的邊。直到剩下兩個點為止。

弄乙個序列a:(全排列),然後我們每次在a中尋找編號最小且沒有在prufer序列**現的點,將它與prufer序列中的第乙個點連邊,然後將這兩個點分別從a和prufer序列中刪掉。最後a中會剩下兩個點,將它們連邊即可。

給定乙個有向帶權圖g和其中乙個節點u,找出乙個以u為根節點,權和最小的有向生成樹。這個生成樹滿足:

就是先找出來前n-1條最小的彼岸,然後如果沒有環就結束,有環就縮點繼續重複上述過程。

inline

bool

solve

(int n,

int m,

int root)

minn[root]=0

;for

(int i=

1;i<=n;i++)}

if(!cnt)

return

true

;for

(int i=

1;i<=n;i++)if

(!id[i]

) id[i]

=++cnt;

for(

int i=

1;i<=m;i++

) n=cnt,root=id[root];}

}

對於有重邊+邊的權值有可能不為1的,我們把鄰接矩陣換成邊權值之和,然後按照上面的方法求出來的是是所有矩陣樹的邊權積之和.(所以說如果計算有重邊的,我們可以直接設邊為1,然後來達到計數的目的)

就是乙個最優檢索的二叉樹(一般都是二叉的),滿足它的葉子節點*深度總和最小.

然後還有哈夫曼編碼:構造的方式是在哈夫曼樹上,連線左節點的邊賦成0,連線右節點的邊賦成,然後從根到葉子節點的所有數連起來,就是該葉子節點的哈夫曼編碼.哈夫曼編碼有乙個特性,就是兩兩之間一定不會出現字首關係

其實就是乙個貪心的思想.把所有葉子節點都放進堆裡,權值為出現次數(檢索次數).我們每次選取兩個權值最小的點,然後將它們合併(合併意為新開乙個節點做它們的父親,然後權值為它們的和).然後一路合併上去,直到只剩下乙個為止.

為什麼這樣子是最優的呢?因為我們的貪心策略,保證了次數小的一定深度最低.

就是每次選取k個,然後合併.但是需要注意一點的是,最後一次合併的時候可能不足k個,這樣的話,如果根的子節點有空的話,顯然不是最優結果,所以我們要計算一下,在合併開始前往佇列裡面新增值為0的節點,補夠空缺

對於同乙個問題,可能有很多種哈夫曼樹的形態.如果要求深度最小,合併的時候還需要按照權值為第一關鍵字,深度為第二關鍵字(從小到大)選取.

ACM模板(5)整數相關計算

acm模板列表 二進位制中1的個數 把整數轉化為字串 把字串轉化為整數 把字串轉化為整數 二進位制中1的個數 int hammingweight int n return ans 把整數轉化為字串 else unum unsigned num 其他情況 轉換 dowhile unum str i 0...

acm學習筆記

include include include int main 在乙個平面內有兩個點,求兩個點分別和原點的連線的夾角的大小。include include define pi 3.1415926 int main return 0 用迭代法求平方根。求平方根的迭代公式為 x n 1 1 2 x n...

ACM 資料結構 線段樹模板

include include using namespace std define maxn 200005 class nodenode maxn int getright int n void build int l,int r,int num node num l l node num r r...