持續更新中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...