樹分治
在樹中將樹分成幾個部分,然後依次解決的方法,這就是一種優化的方法。那麼要如何去分治一棵樹呢,這裡需要乙個概念,那就是樹的質心
那麼什麼是樹的質心呢
指的是讓這棵樹中的乙個點為根,使得這棵樹的最大子樹的節點數最少
這就是樹的質心。
那麼要怎麼找出乙個樹的質心呢。
假設是這樣的一棵樹,可見的這棵樹含有三個子樹,要尋找這棵樹的最大子樹,那麼久需要比較以這顆樹中的任意乙個節點為根,比較所有的子樹的大小,記錄最大子樹中最小的乙個。那麼我們要做的就是如何使得能夠找出以任意乙個節點為根節點的最大子樹。
那麼就需要遍歷所有的節點,這裡首先需要乙個存圖的資料結構,那麼存圖又有兩種形式,一種是鄰接表,一種是鄰接矩陣。
這裡的話我們使用鄰接表
void add(int u,int v)
這是鄰接表的寫法,每次傳入兩個引數,這裡的兩個引數是指一條邊的兩個點。將這條邊的終點存放在陣列edge[i].to中,然後這個陣列是乙個結構體陣列這樣的陣列還含有另乙個引數,而這個引數儲存的是這條邊是以u為起點的第幾條邊。
接下來就是讓子樹1和這棵樹剩下的其他子樹的和一起比較,比如子樹1和子樹2和3一起形成的子樹比較。這樣的比較就是為了排除一種極端的情況,就是當子樹1十分的大的時候,比2和3加起來還要大。比較完了之後,
然後是子樹2和子樹1比較大小,然後就是上面的子樹2和子樹1和3比較。
最後就是2和3 比較。這樣一次次的遞迴下來就能找出最大子樹的最小節點數的子樹。
#include
#include
#include
using namespace std;
struct node
edge[40005];
int son[40005],head[40005];
int cnt=0,size=0x3f3f3f3f,n,ans;
int vis[40005];
void add(int u,int v)
void init()
int max(int a,int b)
else
}
int dfs(int u)
}
tmp=max(tmp,n-son[u]-1);
if(tmp
}
int main()
dfs(1);
printf("%d %d\n",ans,size);
}
return 0;
}
分治入門 樹分治
分治思想 劃分子問題,解決子問題,合併子問題 題目 poj1741 題意 給定一棵含有n個節點的無向帶權樹,滿足距離 k的兩點共有多少對?n 1e4 題解 1 首先找到樹a的重心,重心指的是乙個節點,將該節點刪去之後剩下的最大子樹的節點數最小 將其作為樹a的根。在數列的分治之中我們是直接去區間的中間...
點分治(樹分治)
將原問題分解成若干相同形式,相互獨立的子問題,各個擊破 一般用來解決有關樹上路徑的統計和詢問 p4178 tree 給定一棵 n 個節點的樹,每條邊有邊權,求出樹上兩點距離小於等於 k 的點對數量。暴力做法 o n2 點分治做法 選擇乙個點作為分治中心,令其為rt做dfs。對於一條路徑path u,...
Tree(樹分治 點分治)
原題 poj 1741 題意 有一棵n個節點的樹,每條邊都有乙個權值,問有多少個節點之間的距離小於等於k,解析 典型的樹分治,對於每一棵樹,我們首先找到它的重心 重心 一棵樹中以這個點為root時的最大子樹的節點數最小 int siz n maxn n 這棵子樹大小,最大子樹大小 void getg...