prufer數列學習筆記

2021-07-09 23:35:43 字數 1884 閱讀 4761

學了一種新姿勢叫prufer數列,可以用來解一些關於無根樹計數的問題。

prufer數列是一種無根樹的編碼表示,對於一棵n個節點帶編號的無根樹,對應唯一一串長度為n-2的prufer編碼。

(1)無根樹轉化為prufer序列。

首先定義無根樹中度數為1的節點是葉子節點。

找到編號最小的葉子並刪除,序列中新增與之相連的節點編號,重複執行直到只剩下2個節點。

如下圖的樹對應的prufer序列就是3,5,1,3。

具體實現可以用乙個set搞定,維護度數為1的節點。複雜度o(nlgn)。

/**********************

給一棵無根樹進行prufer編碼

**********************/

#include #include #include #include #include #include #include #include using namespace std;

#define maxn 1111111

#define maxm 2111111

set gg;

struct node edge[maxm];

int n, head[maxn], cnt, degree[maxn];

bool vis[maxn];

void add_edge (int u, int v)

int main ()

for (int i = 1; i <= n; i++)

} set::iterator it;

int prufer[maxn], id = 0;

for (; id <= n-3;)

} }for (int i = 1; i <= id; i++) cout << endl;

return 0;

}

(2)prufer序列轉化為無根樹。

設點集v=,每次取出prufer序列中最前面的元素u,在v中找到編號最小的沒有在prufer序列中出現的元素v,給u,v連邊然後分別刪除,最後在v中剩下兩個節點,給它們連邊。最終得到的就是無根樹。

具體實現也可以用乙個set,維護prufer序列中沒有出現的編號。複雜度o(nlgn)。

/**********************

prufer序列解碼

**********************/

#include #include #include #include #include #include #include #include using namespace std;

#define maxn 1111111

#define maxm 2111111

int n;

int prufer[maxn], node[maxn], cnt;

setgg; //在prufer序列裡沒有出現的點

int vis[maxn]; //這個點是不是在prufer序列裡面

bool used[maxn]; //這個點有沒有使用過

int main ()

for (int i = 1; i <= n; i++)

} set::iterator it;

for (int i = 1; i <= n-2; i++)

} it = gg.begin ();

cout << *it << "-" << *(++it) << endl;

return 0;

}

最後有乙個很重要的性質就是prufer序列中某個編號出現的次數+1就等於這個編號的節點在無根樹中的度數。

prufer編碼學習筆記

對於乙個無根樹,他的 prufer 編碼是這樣確定的 那麼,通過給定的無根樹求 prufer 編碼就很簡單了 比如下面這個無根樹,它的 prufer 編碼就是 texttt 這個 prufer 編碼有一些很顯然的性質 首先長度肯定是 n 2 但每個元素可能相同,然後對於每個無根樹,它的 prufer...

prufer 序列 學習筆記

上周五看了一下,發現不是很難,今天再看了一眼,把板題做了,順便看了另外一道 懶得碼了 其實很簡單,我們定義一顆無根樹的 prufer 序列為,欽定任意乙個點為根 方便確定父子關係 每次從葉子中選出乙個編號最小的點,把它的父親加入到 prufer 序列中,並刪掉該節點。不難看出,我們最後會有 n 2 ...

斐波那契數列 學習筆記

先熟悉一下斐波那契數列 比如下邊這個數列 0,1,1,2,3,5,8,13,21.在遞迴上這個方法定義為 f 0 0 f 1 1 f n f n 1 f n 2 接下來我們推一下斐波那契數列的通項公式 待定係數法 設常數r,s使得 f n rf n 1 s f n 1 r f n 2 這個公式為一下...