SDOI2006 保安站崗 洛谷p2458

2021-08-30 10:48:24 字數 3479 閱讀 2313

五一來臨,某地下超市為了便於疏通和指揮密集的人員和車輛,以免造成超市內的混亂和擁擠,準備臨時從外單位呼叫部分保安來維持交通秩序。

已知整個地下超市的所有通道呈一棵樹的形狀;某些通道之間可以互相望見。總經理要求所有通道的每個端點(樹的頂點)都要有人全天候看守,在不同的通道端點安排保安所需的費用不同。

乙個保安一旦站在某個通道的其中乙個端點,那麼他除了能看守住他所站的那個端點,也能看到這個通道的另乙個端點,所以乙個保安可能同時能看守住多個端點(樹的結點),因此沒有必要在每個通道的端點都安排保安。

程式設計任務:

請你幫助超市經理策劃安排,在能看守全部通道端點的前提下,使得花費的經費最少。

輸入格式:

第1行 n,表示樹中結點的數目。

第2行至第n+1行,每行描述每個通道端點的資訊,依次為:該結點標號i(0對於乙個n(0 < n <= 1500)個結點的樹,結點標號在1到n之間,且標號不重複。

輸出格式:

最少的經費。

如右圖的輸入資料示例

輸出資料示例:

輸入樣例#1:複製

6

1 30 3 2 3 4

2 16 2 5 6

3 5 0

4 4 0

5 11 0

6 5 0

輸出樣例#1:複製

25
樣例說明:在結點2,3,4安置3個保安能看守所有的6個結點,需要的經費最小:25

(以下全部都是對於要覆蓋任意乙個以x為根的子樹來說的)

(其中我們設y節點為y的兒子,fa為x的父親)

1.x節點被自己覆蓋,即選擇x點來覆蓋x點

2.x節點被兒子y覆蓋,即選擇y點來覆蓋x點

3.x節點被父親fa覆蓋,即選擇fa點來覆蓋x點

藉此三種狀態,我們可以設f[x][0/1/2]為讓以x為根的子樹中的節點全部被覆蓋,且x點的被覆蓋情況為1/2/3時的最小代價為了方便,我們不妨設這三種情況分別為:

1.f[x][0]---對應上面的1

2.f[x][1]---對應上面的2

3.f[x][2]---對應上面的3

既然是dp,總是有轉移方程的,我們想一下dp方程要如何設計

(1):對應上面的1.

f[x][0]=∑ min(f[y][0],f[y][1],f[y][2]) + val[x]

其中val[x]是選擇x點的代價

我們很容易想到,在節點x被選擇之後,我們就可以無拘無束了(蛤?),也就是說對於x兒子節點y的狀態可以不去考慮,因為x節點被選擇之後y節點無論如何也會被覆蓋到,所以我們在兒子y的所有狀態裡取min,累加起來就行了

(2):對應上面的3(先講3,因為2比較難以理解,放到了後面)

f[x][2]=∑ min(f[y][0],f[y][1])

為什麼3情況對應的轉移方程要這樣寫呢?

我們不妨這樣理解,對於x節點我們讓它的父親節點fa覆蓋它,那麼根據我們的狀態設計,此時必須要滿足以x的兒子y為根的子樹之中所有點已經被覆蓋

那麼這時就轉化為乙個子問題要讓y子樹滿足條件只有兩種決策:要麼y被y的兒子覆蓋,要麼被y自己覆蓋(即選擇y節點),只需要在y的這兩種狀態取min累加就可以了

(3):對應上面的2(duangduangduang 敲黑板劃重點啦)

f[x][1]=∑ min(f[y][0],f[y][1]),如果選擇的全部都是f[y][1],要再加上min(f[y][0]-f[y][1])

這又是什麼意思呢?真是讓人摸不著頭髮,,,質壁分離(逃

到了這裡,我們就要回顧一下我們設計的dp狀態了:

設f[x][0/1/2]為讓以x為根的子樹中的節點全部被覆蓋,且x點的被覆蓋情況為1/2/3時的最小代價

先提示一下,如果你理解了下面,那麼本題是很簡單的。。如果你沒理解,就返回到這裡再看一遍吧,我就在這裡等著你

咳咳。。說正經的。。(逃

對於此時的狀態,f[x][1]代表對於節點x讓x被自己的兒子覆蓋,那麼和分析(2)一樣,都要先滿足此時以y的子樹已經滿足了條件,才能進行轉移,這就是前面那部分:∑ min(f[y][0],f[y][1])的來歷,那麼後面那一長串又是怎麼回事呢?

我們可以這樣理解,此時既然要保證x點是被自己的兒子覆蓋的,那麼如果此時y子樹已經滿足了全部被覆蓋,但是y此時被覆蓋的狀態卻是通過y節點自己的兒子達到的,那麼x就沒有被兒子y覆蓋到,那麼我們不妨推廣一下,如果x所有的兒子y所做的決策都不是通過選擇y點來滿足條件,那麼我們就必須要選擇x的乙個子節點y,其中y滿足f[y][0]-f[y][1]最小,並把這個最小的差值累加到f[x][1]中去這樣才能使得x點被自己的兒子覆蓋,狀態f[x][1]也才能合理地得到轉移

好了,如果你還是沒有太懂這個(3)的設計過程,請你回到之前再仔細看幾遍

如果你已經理解了上面,那麼恭喜你這個題,你已經a掉了

因為轉移方程既然有了,那麼我們就只需要最後的答案了

由於題目中沒有說這棵樹的根節點是哪個,所以你可以預設1就是根,或者開乙個陣列在加邊的時候記錄一下每個點的入度,最後沒有入度的點就是根(但好像沒有區別,畢竟我a掉了)

最後答案即為min(f[root][0],f[root][1])

因為根節點沒有父親,所以不需要考慮它的f[root][2]狀態

那這樣的花。。下面就放一下我醜陋的**好了(逃

還請dalao們不喜勿噴

ps:**裡也有解釋,希望能幫到你更深地理解一下本題

#include#define f(i,l,r) for(i=(l);i<=(r);i++)

using namespace std;

const int maxn=3005,inf=100000000;

struct edgee[maxn<<1];

int f[3][maxn<<1],h[maxn<<1],tot,n;

int a[maxn<<1];

inline void add(int u,int v)

void dfs(int u,int fa)

}dfs(1,-1);

cout<

return 0;

}

SDOI2006 保安站崗

看到題目之後 果斷樹形dp啊!但是怎麼樹形dp啊qwq。開始想的是 dp i 0 1 來表示i節點擊不選擇。那麼狀態轉移方程 dp i 0 sum dp v 1 dp i 1 val i sum min dp v 0 dp v 1 然後如果所有小的都是dp v 0 找乙個最小的dp v 1 加上,然...

SDOI 2006 保安站崗

洛谷傳送門 五一來臨,某地下超市為了便於疏通和指揮密集的人員和車輛,以免造成超市內的混亂和擁擠,準備臨時從外單位呼叫部分保安來維持交通秩序。已知整個地下超市的所有通道呈一棵樹的形狀 某些通道之間可以互相望見。總經理要求所有通道的每個端點 樹的頂點 都要有人全天候看守,在不同的通道端點安排保安所需的費...

SDOI 2006 保安站崗

給出一棵 n 個節點以 1 為根的樹,乙個節點的覆蓋半徑是 1 點有點權 val x 選擇一些點,使得點權和最小,同時每個節點要麼被選擇要麼被周圍的點覆蓋。樹形dp 的討論。注意到覆蓋有可能呈現出兩層都沒有選點的情況 下面被子樹覆蓋,上面被父節點覆蓋 所以狀態設計要注意。設 f i 0 1 2 表示...