廢話不說,直接進入正題。在這裡本題將介紹四種方法。
演算法一:在樹中,最短路等於最長路,因此我們可以用floyd演算法求每兩點間的距離,並找出直徑。然後列舉直徑上的核,模擬得出偏心距。這樣的演算法時間複雜度是o(n^3)。在這裡有乙個性質,對於每條直徑都有核,而最小偏心距是唯一的,所以我們只要列舉其中一條直徑就可以了,證明就略啦。
且對於直徑上的一條路徑f,它的偏心距是可以在o(1)的時間內求出來的。
ecc:=max,min};
其中st、ed為直徑兩端,i、j為線段兩端。證明如下:我們假設存在非直徑端點的一點k,如果dis[k,i]dis[i,st]那麼當前的直徑就不是最長的路徑,就和它是直徑相矛盾,所以我們對於一條直徑上的路徑可以得到如上計算偏心距的方法。
這裡貼一下**吧。
view code
1演算法二:樹形動態規劃。 演算法首先要求我們找出一條路徑(這可以通過著名的「兩次bfs」演算法得到),然後,選取任意乙個在直徑上的點作為根節點建立有根樹,通過經典樹形動態規劃確定節點的最長下降路和次長下降路。var i,j,n,m,k,l,x,y,z,ans:longint;
2 f,a:array[0..300,0..300]of longint;
3 b:array[0..300]of longint;
4function max(a,b:longint):longint;
5begin
6if a>b then exit(a) else exit(b);
7end;
8function min(a,b:longint):longint;
9begin
10if athen exit(a) else exit(b);
11end;
12begin
13 assign(input,'
core.in
');reset(input);
14 assign(output,'
core.out
');rewrite(output);
15 readln(n,m);
16 fillchar(f,sizeof(f),63);
17for i:=1
to n do f[i,i]:=0;
18for i:=1
to n-1
do19
begin
20 read(x,y,z);
21 f[x,y]:=z;
22 f[y,x]:=z;
23end;
24for k:=1
to n do
25for i:=1
to n do
26for j:=1
to n do
27if (f[i,j]>f[i,k]+f[k,j]) then
28begin
29 f[i,j]:=f[i,k]+f[k,j];
30end;
31 k:=0;
32for i:=1
to n do
33for j:=1
to n do
34if f[i,j]>k then
35begin
36 k:=f[i,j];
37 x:=i;y:=j;
38end;
39 l:=0;
40for i:=1
to n do
41if f[x,i]+f[i,y]=f[x,y] then
42begin
43 inc(l);
44 b[l]:=i;
45end;
46 ans:=maxlongint;
47for i:=1
to l do
48for j:=1
to l do
49begin
50if f[b[i],b[j]]>m then continue;
51 k:=max(min(f[x,b[i]],f[x,b[j]]),min(f[b[i],y],f[b[j],y]));
52if kthen ans:=k;
53end;
54 writeln(ans);
55 close(input);close(output);
56end.
然後,演算法列舉路徑的起點。然後基於下述事實:合法路徑只能向最長下降路方向延伸。(如果不是這樣,則最長下降路不能被遮蔽,其偏心矩一定不會是最小;另外,合法路徑不能像兩條路上延伸,因為我們列舉的是路徑的起點)。通過這個事實,很容易進行乙個簡單的樹形動態規劃在o(n)的時間內對於每乙個確定的起點給出這種情形下的最小偏心矩。
該演算法的時間複雜度為o(n2),且簡潔明瞭,是本題的正統演算法。
演算法三:貪心性質+二分答案。 如果我們已經知道了最小偏心矩,同時也知道指定的有根樹中根必然在核上,則我們可以對每乙個節點作一次從下到上的遍歷,一旦長度超過給出的最小偏心矩,就將接下來的節點進行標記。(當然,這個過程直接進行的複雜度是o(n2)的,但是借鑑演算法二中的動態規劃,我們可以很輕鬆地通過自上而下的規劃把複雜度降到o(n))。然後,我們觀察被標記的節點(這些節點必須在核上)是否能夠形成一條滿足題意的核。
要形成滿足題意的核,必須滿足這樣幾個條件:
1、 必須形成一條路徑,不能有分支。
2、 必須向最長下降路或者是在直徑上的次長下降路進行延伸。
3、 路徑的長度不能超過s.
以上的3點判斷都能在o(n)的動態規劃中予以驗證。故本題可以在o(n)的時間內完成對某乙個已知最小偏心矩的判斷。
鑑於最小偏心矩的可行性是單調的,我們採用二分答案的方法可以解決本題,演算法得時間複雜度為o(nlogc),其中c是給定 的圖中直徑的長度。從本題來看,c <= 300,000
演算法四:單調佇列。
我們先看乙個性質。對於圖中的每一條直徑,都存在一段滿足題意的核。題目說過了,直徑與直徑之間必然交於固定的一點。因此證明我們可以這麼想,假設有兩條直徑,型如「>——
言歸正傳,首先還是通過「兩次bfs」給出圖中的直徑長度以及一條具體的直徑。然後,對於該條直徑而言,對於上面的路徑的偏心距,可以用前面講過的方法求,與演算法一的差別就在於這裡我們使用單調佇列來維護這個最小的偏心距。整個演算法的複雜度為o(n),是本題的最好演算法。
NOIP2007 樹網的核
參考了某位神牛的題解之後才發現原來這道題並不是很難 還是自己太弱了 原來的想法本來是快排找直徑,通過dfs確定在直徑中的點,然後再分別列舉每兩個點形成的邊,以邊的兩點做floyd通過打擂台確定偏心距。自己的想法真的很麻煩而且就算編出來少說也要200 行的 這在比賽中是不可能也是做不到的。正規且高效的...
NOIp 2007 樹網的核
問題描述 設 t v,e,w 是乙個無圈且連通的無向圖 也稱為無根樹 每條邊帶有正整數的權,我 們稱t 為樹網 treenetwork 其中v,e分別表示結點與邊的集合,w 表示各邊長度的集合,並設t 有n個結點。路徑 樹網中任何兩結點a,b 都存在唯一的一條簡單路徑,用d a,b 表示以a,b 為...
noip2007 樹網的核
樹網的核 題目描述 設t v,e,w 是乙個無圈且連通的無向圖 也稱為無根樹 每條邊到有正整數的權,我們稱t為樹網 treebetwork 其中v,e分別表示結點與邊的集合,w表示各邊長度的集合,並設t有n個結點。路徑 樹網中任何兩結點a,b都存在唯一的一條簡單路徑,用d a,b 表示以a,b為端點...