講師:張秉中
好像有點多...
以1為根結點
7的子樹
subtree
5的祖先
ancestor
以1為根結點
深度(degree):
根結點到此節點的最短距離
0
1
2
3
4
以1為根結點
葉節點:沒有子節點的節點
diameter
樹上距離最遠的點對
0
1
1
1
2
2
2
2
3
4
5
5
0
1
2
2
3
4
5
5
3
6
6
6
0
1
2
2
3
4
5
5
3
6
6
6
DP on tree
給一棵以節點1為根大小為N(N<2e5)的樹,求樹上各點子樹大小-1
#include <bits/stdc++.h>
using namespace std;
const int mxn = 2e5+10;
vector<int> childs[mxn];
int sz[mxn] = {};
int n;
void dfs(int now){
sz[now] = 1;
for(auto nxt:childs[now]){
dfs(nxt);
sz[now] += sz[nxt];
}
return;
}
int main(){
cin>>n;
for(int i = 2;i<=n;i++){
int p;
cin>>p;
childs[p].push_back(i);
}
dfs(1);
for(int i = 1;i<=n;i++)cout<<sz[i]-1<<' ';
return 0;
}
{1}
{1}
{1}
{1}
{1}
{1}
{2}
{2,2}
{1}
{1}
{1}
{2}
{2,2}
{max({2})+1,
max({2,2})+1}
{1}
{1}
{1}
{2}
{2,2}
{3,3}
{max({3,3})+1}
{1}
{1}
{1}
{2}
{2,2}
{3,3}
{4}
{1}
{1}
{1}
{2}
{2,2}
{3,3}
{4}
{1}
{1}
{1}
{2,2}
{3,5,2}
在DFS一次
如果只有一個子節點則答案為
max(目前答案,該節點值)
否則答案為
max(目前答案,該節點最大值+次大值-1)
{1}
{1}
{1}
{2}
{2,2}
{3,3}
{4}
{1}
{1}
{1}
{2,2}
{3,5,2}
{1}
{1}
{1}
{2}
{2,2}
{3,3}
{4}
{1}
{1}
{1}
{2,2}
{3,5,2}
3+5-1=7
1
4
2+2-1=3
1
1
1
1
2
1
2+2-1=3
3+3-1=5
{1}
{1}
{1}
{2}
{2,2}
{3,3}
{4}
{1}
{1}
{1}
{2,2}
{3,5,2}
3+5-1=7
1
4
2+2-1=3
1
1
1
1
2
1
2+2-1=3
3+3-1=5
如果好好做的話,時間複雜度為O(n)
centroid
(對不起我只會一種作法)
#include <bits/stdc++.h>
using namespace std;
struct node{
int par,sz;
vector<int> childs;
node(){
par = -1,sz = 1;
}
};
int n;
vector<node> tree;
void get_sz(int now){
for(auto nxt:tree[now].childs){
if(nxt == tree[now].par)continue;
tree[nxt].par = now;
get_sz(nxt);
tree[now].sz += tree[nxt].sz;
}
return;
}
int get_centroid(int now){
for(auto nxt:tree[now].childs){
if(nxt == tree[now].par)continue;
if(tree[nxt].sz>n/2)return get_centroid(nxt);
}
return now;
}
int main(){
cin>>n;
tree = vector<node>(n+1,node());
for(int i = 0;i<n-1;i++){
int a,b;
cin>>a>>b;
tree[a].childs.push_back(b);
tree[b].childs.push_back(a);
}
get_sz(1);
cout<<get_centroid(1);
}
tree flattening
樹鍊剖分
heavy-light decomposition(HLD)
#include <bits/stdc++.h>
using namespace std;
struct node{
int link_top,depth,sz,par,big_son;
vector<int> childs;
node(){
link_top = -1;
depth = -1;
sz = 1;
big_son = -1;
}
};
vector<node> tree;
vector<int> time_stamp;
void dfs1(int now){
for(auto nxt:tree[now].childs){
if(nxt == tree[now].par)continue;
tree[nxt].par = now;
tree[nxt].depth = tree[now].depth+1;
dfs1(nxt);
if(tree[now].big_son == -1 || tree[tree[now].big_son].sz<tree[nxt].sz)tree[now].big_son = nxt;
tree[now].sz += tree[nxt].sz;
}
return;
}
void dfs2(int now,int top){
time_stamp.push_back(now);
tree[now].link_top = top;
if(tree[now].big_son != -1)dfs2(tree[now].big_son,top);
for(auto nxt:tree[now].childs){
if(nxt == tree[now].par||nxt == tree[now].big_son)continue;
dfs2(nxt,nxt);
}
return;
}
int lca(int a,int b){
int ta = tree[a].link_top,tb = tree[b].link_top;
while(ta != tb){
if(tree[ta].depth>tree[tb].depth){
swap(ta,tb);
swap(a,b);
}
//update link
b = tree[tb].par;
tb = tree[b].link_top;
cout<<a<<' '<<b<<endl;
}
if(tree[a].depth>tree[b].depth){
swap(a,b);
}
//update link(更新同鏈上的兩節點)
return a;
}
int main(){
int n;
cin>>n;
tree = vector<node>(n+1,node());
for(int i = 1;i<=n-1;i++){
int a,b;
cin>>a>>b;
tree[a].childs.push_back(b);
tree[b].childs.push_back(a);
}
dfs1(1);
dfs2(1,1);
}
O(log(n))
centroid decomposition
#include <bits/stdc++.h>
using namespace std;
struct node{
int sz;
int parent;
bool del;
int val;
vector<int> childs;
node(){
parent = -1;
del = false;
val = -1;
}
};
vector<node> tree;
vector<node> centree;
void get_sz(int now,int par){
tree[now].sz = 1;
for(auto nxt:tree[now].childs){
if(nxt == par||tree[nxt].del)continue;
get_sz(nxt,now);
tree[now].sz += tree[nxt].sz;
}
return;
}
int find_centroid(int now,int par,int tar){
for(auto nxt:tree[now].childs){
if(nxt == par||tree[nxt].del)continue;
if(tree[nxt].sz>tar)return find_centroid(nxt,now,tar);
}
return now;
}
int cendfs(int now,int par){
get_sz(now,now);
int cen = find_centroid(now,now,tree[now].sz/2);
tree[cen].del = true;
centree[par].childs.push_back(cen);
centree[cen].parent = par;
for(auto nxt:tree[cen].childs){
if(tree[nxt].del)continue;
cendfs(nxt,cen);
}
return cen;
}
int main(){
int n;
cin>>n;
tree = vector<node>(n+1,node());
centree = vector<node>(n+1,node());
for(int i = 0;i<n-1;i++){
int a,b;
cin>>a>>b;
tree[a].childs.push_back(b);
tree[b].childs.push_back(a);
}
int root = cendfs(1,0);
dfs(root,root);
}
O(n)
O(size(11))
O(size(15))
O(size(14))
複雜度O(nlog(n)+qlog(n)log(n))或O((n+q)log(n))
看有沒有優化LCA
其實是講師不會的