學了一種新姿勢叫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 這個公式為一下...