樹的重心
樹的重心定義為:找到乙個點,其所有的子樹中最大的子樹節點數最少,那麼這個點就是這棵樹的重心,刪去重心後,生成的多棵樹盡可能平衡.模板:實際上樹的重心在樹的點分治中有重要的作用, 可以避免n^2的極端複雜度(從退化鏈的一端出發),保證nlogn的複雜度, 利用樹型dp可以很好地求樹的重心.求樹的重心
//樹的重心可能有兩個
//做法:從任意點出發,dfs遍歷整棵樹,在回溯的過程中,維護每個子樹的結點個數以及這個結點的最大子樹節點個數
樹的直徑#include
#include
#include
#include
#include
using namespace std;
const
int manx=
5e4+10;
const
int inf=
1e9;
int head[manx]
,dp[manx][2
],vs[manx]
;//0表示子樹結點個數,1表示最大子樹結點個數
int n,cou=
0,ans=inf,root1=
0,root2=
0,flag=0;
struct node
edge[manx<<1]
;void
add(
int s,
int e)
; head[s]
=cou++;}
void
dfs(
int root)
} dp[root][0
]++; dp[root][1
]=max(dp[root][1
],n-dp[root][0
]);if
(dp[root][1
]else
if(dp[root][1
]==ans)
}int
main()
dfs(1)
;if(!flag)
printf
("%d\n"
,root1)
;else
printf
("%d %d\n"
,min
(root1,root2)
,max
(root1,root2));
}
定義:另外數的直徑這裡有乙個引理,樹的所有直徑擁有相同的中點求法二有兩種寫法,但都在再回溯時維護最長鏈:一棵樹的直徑就是這棵樹上存在的最長路徑。
求法1:
兩次dfs或bfs。第一次任意選乙個點進行dfs(bfs)找到離它最遠的點,此點就是最長路的乙個端點,再以此點進行dfs(bfs),找到離它最遠的點,此點就是最長路的另乙個端點,於是就找到了樹的直徑。樹的直徑求法及證明
求法2:
設定狀態dp[u][2]
dp[u][0]表示距離u的最長距離,dp[u][1]表示距離u的次長距離(與最長距離的節點不在同一顆子樹上)然後狀態方程為
ans=(ans,dp[u][0]+dp[u][1])ans為樹的直徑答案樹的直徑(樹形dp)
模板:1、遞迴出去時維護每個點深度,回溯時維護最大深度
2、只在回溯時維護最遠和次遠距離(離當前結點最遠/次遠的葉子結點)void
dfs(
int now,
int fa)if(
!flag)
}
整體**:void
dfs(
int now,
int fa)
else
if(dp[now][1
]]+nlen)
dp[now][1
]=dp[net][0
]+nlen;
} ans=
max(ans,dp[now][0
]+dp[now][1
]);}
例題1:#include
#include
#include
#include
using namespace std;
const
int manx=
4e4+10;
const
int inf=
0x3fffffff
;int n,m,cou,ans;
int deep[manx]
,dp[manx]
,head[manx]
;//dp存最大深度
struct node
}edge[manx<<1]
;void
add(
int s,
int e,
int len)
void
init()
void
dfs(
int now,
int fa)if(
!flag)
}int
main()
deep[1]
=0;dfs(1
,0);
printf
("%d\n"
,ans)
;return0;
}
兩次dfs解法:f. three paths on a tree
例題2:樹的直徑+貪心)
例題3:樹上子鏈: 附:
樹的直徑 樹的重心
樹的直徑 定義 那麼樹上最遠的兩個點,他們之間的距離,就被稱之為樹的直徑。樹的直徑的性質 1.直徑兩端點一定是兩個葉子節點。2.距離任意點最遠的點一定是直徑的乙個端點,這個基於貪心求直徑方法的正確性 可以得出。3.對於兩棵樹,如果第一棵樹直徑兩端點為 u,v 第二棵樹直徑兩端點為 x,y 用條邊將兩...
求樹的重心 樹的直徑
樹的重心 樹的重心是指樹上一點,去掉後最大子樹可以取得最小值的點。求解方法 樹的重心定義 去掉該點後最大子樹大小不超過n 2。重心為1 樹的直徑指樹上最遠兩點的距離 方法 先隨便找個點,找到離他最遠的點,再在那個最遠的點上找一次最遠的點,這兩個點之間的距離就是直徑。include define ma...
樹的直徑與重心
樹的直徑,指樹上最長的不重複經過同乙個點的路徑。方法 先從任意一點p pp出發,找離它最遠的點q qq,再從點q qq出發,找離它最遠的點w ww,w ww到q qq的距離就是的直徑 具體實現可以使用兩次dfs dfsdf s。演算法證明 反證法 include using namespace st...