【算法-树论】树的直径
定义
树上任意两节点之间最长的简单路径即为树的直径。
寻找方法:两遍 dfs 或树形 DP。
dfs 方法:
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int man = 1e4+10;
class Graph_D {
public:
int hed[man], len = 1;
int nxt[man<<1], ver[man<<1];
void Ins (int u, int v) {
ver[++len] = v;
nxt[len] = hed[u];
hed[u] = len;
return ;
}
void DIns (int u, int v) {
Ins(u, v), Ins(v, u);
return ;
}
} G;
int n, k, l, r, mal;
bool vis[man];
void dfs (int x, int len) {
vis[x] = 1;
if (mal < len) mal = len, r = x;
for (int i = G.hed[x]; i; i = G.nxt[i]) {
int v = G.ver[i];
if (!vis[v]) dfs(v, len+1);
} vis[x] = 0;
return ;
}
int main () {
#ifndef ONLINE_JUDGE
freopen("test.in", "r", stdin);
freopen("test.out", "w", stdout);
#endif
scanf("%d", &n);
for (int u, v, i = 1; i < n; ++ i) scanf("%d%d", &u, &v), G.DIns(v, u);
dfs(1, 0);
l = r, mal = 0;
dfs(l, mal);
printf("%d", mal);
return 0;
}
(若要记录直径节点,则在第二次深搜时记录前端节点。)
树形 DP 方法:
记录每个节点的最长路径 \(dep1\) 和次长路径 \(dep2\)。
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int man = 1e4+10;
class Graph_D {
public:
int hed[man], len = 1;
int nxt[man<<1], ver[man<<1];
void Ins (int u, int v) {
ver[++len] = v;
nxt[len] = hed[u];
hed[u] = len;
return ;
}
void DIns (int u, int v) {
Ins(u, v), Ins(v, u);
return ;
}
} G;
int n, res;
int dep1[man] = {-1}, dep2[man] ={-1};
void dfs (int x, int fa) {
dep1[x] = dep2[x] = 0;
for (int i = G.hed[x]; i; i = G.nxt[i]) {
int v = G.ver[i];
if (v == fa) continue;
dfs(v, x);
int d = dep1[v]+1;
if (d > dep1[x]) dep2[x] = dep1[x], dep1[x] = d;
else if (d > dep2[x]) dep2[x] = d;
} res = max(res, dep1[x]+dep2[x]);
return ;
}
signed main (void) {
#ifndef ONLINE_JUDGE
freopen("test.in", "r", stdin);
freopen("test.out", "w", stdout);
#endif
scanf("%d", &n);
for (int u, v, i = 1; i < n; ++ i) scanf("%d%d", &u, &v), G.DIns(v, u);
dfs(1, 0);
printf("%d", res);
return 0;
}

浙公网安备 33010602011771号