樹的直徑【模板】

樹的直徑求解法有兩種,一種是樹形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); 
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章