樹的直徑求解法有兩種,一種是樹形dp,另一種是兩次dfs/bfs
這邊有詳細的知識點
推薦兩道入門題 poj-1985, poj-2631
牛客小白月賽22 B題
樹形dp
可以有效處理負邊權,對於記錄路徑信息的效率較低
代碼片
省略了鏈式前向星建樹
const int N=1e5+10;
struct Edge{
int to, next, w;
}e[N*2];
int head[N], cnt;
int dis[N]; //記錄每個點到葉子節點的最大距離
int ans; //記錄最大值(直徑)
void dp(int u, int fa) {
int mx1=0, mx2=0;
for(int i=head[u]; i; i=e[i].next) {
int v=e[i].to, w=e[i].w;
if ( v==fa ) continue; //碰到父結點跳過
if ( mx1<dis[v]+w ) {
mx2=mx1;
mx1=dis[v]+w;
}
else if ( mx2<dis[v]+w ) {
mx2=dis[v]+w;
}
}
dis[u]=mx1;
ans=max(ans,mx1+mx2);
}
dfs/bfs
可以通過pre數組處理路徑信息
無法處理負邊權
const int N=1e5+10;
struct Edge{
int to, next, w;
}e[N*2];
int head[N], cnt;
int dis[N];
int ans;
int start; //多一個結點記錄 初始結點
void dfs(int u, int fa) {
if ( dis[u]>ans ) {
ans=dis[u];
start=u;
}
for(int i=head[u]; i; i=e[i].next) {
int v=e[i].to, w=e[i].w;
if ( v==fa ) continue;
dis[v]=dis[u]+w;
dfs(v,u);
}
}
void solve() {
//建樹省略
memset(dis,0,sizeof(dis));
ans=0;
dfs(1,0);
dfs(start,0);
}