HDU 4607 Park Visit 樹的直徑

2021-06-23 03:45:24 字數 1464 閱讀 6125

題意:有n個節點,m個詢問,接著給出n-1條邊,詢問要訪問k個點的最短距離

**)一棵樹,問從任意點出發,每次訪問k個點走過的最少的邊數

思路:我們可以這樣考慮,假設我們走的起點為s,終點為t,那麼路徑s-t上的點我們必須都走到(因為是一棵樹),那麼如果路徑s-t上的點大於或等於k,則我們只需要沿著路徑一直走就行,所以最小長度為k-1,否則,我們一定是在路徑上的一些點停下,然後轉向其他分支然後再回來,此時才能滿足一共走過k個點。假設從s到t的路徑上一共有num個點,則最後我們要求的答案ans=num-1+?,這個?即為中間點(可以包括s和t)到別的分支再回來所要走的最小距離,因為每個分支互不影響,所以我們可以對每乙個分支分開求,因為圖為一棵樹,所以我們即是求一棵子樹從根節點到他的子節點中遍歷x點再回來所要走的最短距離,我們可以有觀察加數學歸納法證明這個值為2*x,即從一棵樹的根結點往他的子樹遍歷x個點再回來的最小距離為2*x,所以?=2*(k-num),所以答案ans=num-1+(k-num)*2,要是這個值最小,則要使num最大,所以我們只要求得該樹的直徑即可,以下時**,求樹的直徑是個很經典的問題了,

演算法證明:**)

樹的直徑(diameter)是指樹上的最長簡單路。

直徑的求法:兩遍bfs (or dfs)

任選一點u為起點,對樹進行bfs遍歷,找出離u最遠的點v

以v為起點,再進行bfs遍歷,找出離v最遠的點w。則v到w的路徑長度即為樹的直徑

*簡單證明

於是原問題可以在o(e)時間內求出

關鍵在於證明第一次遍歷的正確性,也就是對於任意點u,距離它最遠的點v一定是最長路的一端。

如果u在最長路上,那麼v一定是最長路的一端。可以用反證法:假設v不是最長路的一端,則存在另一點v』使得(u→v』)是最長路的一部分,於是len(u→v』) > len(u→v)。但這與條件「v是距u最遠的點」矛盾。

如果u不在最長路上,則u到其距最遠點v的路與最長路一定有一交點c,且(c→v)與最長路的後半段重合(why?),即v一定是最長路的一端

因為是樹是連通的,所以u必有一條路徑c和最長路徑l相交,len(c)>=1,l被分為兩部分,一部分l1,一部分l2

假設第一次dfs過後,所求最長路徑lu端不在l上,那麼len(lu)>=len(c)+len(l1)(l1,l2對稱,取l1或者l2都一樣)

len(l2+c+lu)>len(l1+l2),矛盾.

#include#include#include#includeusing namespace std;

#define max 100005

#define ll __int64

#define for(n) for(int i=0;i<(n);i++)

vectortree[max];

int d[max];

void init(int n)

void dfs(int u,int f,int step)

}return 0;

}

HDU4607 樹的直徑

樹的直徑的求法,任取一點u為起點,bfs出一條最長路徑,假設此時終點為v,則再次以v為起點,再bfs出一條最長路徑v w。可以得出樹的直徑即為所求。證明略。可以直接bfs或者dfs都行,來發水題 author crazy 石頭 data structure 樹的直徑 created time 201...

樹的直徑 hdu 4607

樹的直徑定義 樹中所有最短路徑的最大值。定義distance a,b 為頂點a與b之間的最短距離。用數學語言表示就是 對於一棵樹 t v,e 彐vx,vy v,v1,v2 v,都有distance v1,v2 distance vx,vy 則把vx到vy的最短路徑稱為樹t的直徑。現在我們來用演算法求...

hdu 4607 求樹的直徑

分析後就是求樹的直徑兩次bfs即可 證明 樹的直徑是指樹的最長簡單路。求法 兩遍bfs 先任選乙個起點bfs找到最長路的終點,再從終點進行bfs,則第二次bfs找到的最長路即為樹的直徑 原理 設起點為u,第一次bfs找到的終點v一定是樹的直徑的乙個端點 證明 1 如果u 是直徑上的點,則v顯然是直徑...