學習樹的直徑前提須知
樹的直徑 是一棵樹的某兩個最深的葉子節點的連線,多用於與圖論算法嵌套考算法
算法內容
競賽須要用到的點
一、很簡單的算法,不會單獨考,學習和熟練使用它的多種狀況學習
樹的直徑略講
很簡單,兩次dfsurl
至於爲何,能夠畫圖模擬一下,由於一次dfs必然會在一棵子樹或者根節點上,每次dfs必然找到一棵子樹的最深的葉子節點,那麼第二次dfs必然找到另一棵子樹的葉子節點,這兩點的惟一路徑就是整棵樹的直徑。由這個定理咱們又能夠獲得,樹的直徑不止一條。spa
代碼以下(參考PT07Z - Longest path in a tree).net
//#define fre yes #include <cstdio> #include <cstring> const int N = 10005; int head[N << 1], to[N << 1], ver[N << 1]; int d[N]; bool Vis[N]; int tot; void addedge(int x, int y) { ver[tot] = y; to[tot] = head[x]; head[x] = tot++; } void dfs(int u) { Vis[u] = true; for (int i = head[u]; ~i; i = to[i]) { int v = ver[i]; if(!Vis[v]) { d[v] = d[u] + 1; dfs(v); } } } int diameter(int n) { int st = 1, mx = -1e9; dfs(st); for (int i = 1; i <= n; i++) { if(d[i] > mx) { mx = d[i]; st = i; } } memset(d, 0, sizeof(d)); memset(Vis, false, sizeof(Vis)); dfs(st); mx = -1e9; for (int i = 1; i <= n; i++) { if(d[i] > mx) { mx = d[i]; } } return mx; } int main() { memset(head, -1, sizeof(head)); static int n; scanf("%d", &n); for (int i = 1; i < n; i++) { int u, v; scanf("%d %d", &u, &v); addedge(u, v); addedge(v, u); } printf("%d\n",diameter(n)); return 0; }
那麼也就會存在另外一個問題,讓你輸出你找的兩個節點的最短路徑code
挺智障的問題,能夠在更新完後獲得兩個節點來搞,也能夠在更新時來搞 前者時間消耗多一點,後者空間消耗多一下 看本身喜愛 這裏就不放代碼了get