bzoj 1086 王室聯邦

2022-05-01 04:42:11 字數 1128 閱讀 9789

「餘」人國的國王想重新編制他的國家。他想把他的國家劃分成若干個省,每個省都由他們王室聯邦的乙個成員來管理。他的國家有n個城市,編號為1..n。一些城市之間有道路相連,任意兩個不同的城市之間有且僅有一條直接或間接的道路。為了防止管理太過分散,每個省至少要有b個城市,為了能有效的管理,每個省最多只有3b個城市。每個省必須有乙個省會,這個省會可以位於省內,也可以在該省外。但是該省的任意乙個城市到達省會所經過的道路上的城市(除了最後乙個城市,即該省省會)都必須屬於該省。乙個城市可以作為多個省的省會。聰明的你快幫幫這個國王吧!

第一行包含兩個數n,b(1<=n<=1000, 1 <= b <= n)。接下來n-1行,每行描述一條邊,包含兩個數,即這

條邊連線的兩個城市的編號。

如果無法滿足國王的要求,輸出0。否則輸出數k,表示你給出的劃分方案中省的個數,編號為1..k。第二行輸出n個數,第i個數表示編號為i的城市屬於的省的編號,第三行輸出k個數,表示這k個省的省會的城市編號,如果有多種方案,你可以輸出任意一種。

題目大意:要你對乙個樹分塊,其中每乙個塊大小在b到3b之間,省會節點不一定要在塊內.

這道題要用貪心的思想做,我們可以從根節點向下搜尋,如果存在乙個節點u,它的子樹大小大於或等於b,那麼我們就將它劃分為乙個省,又由於我們是從上往下搜尋的,往上遞迴時就會優先把下面的節點劃分為乙個省.所以我們劃分的省是符合要求的.最後還會有剩餘的節點,我們其實是可以將它劃分到最後乙個省份的(原因?自己思考下).由於剩下的節點一定是小於b的(不然又可以獨立劃分乙個了),所以我們可以直接把剩餘節點全部丟到最後乙個省就完成了劃分.省會就是該省的根節點.

具體做法我們可以用棧來維護.

具體看**:

#include static const int maxm=1e6+10;

int stack[maxm],fst[maxm],nxt[maxm],to[maxm],root[maxm],bel[maxm];

int cnt,top,b,num,n;

void ins(int f,int t)

void dfs(int x,int ftr)

}stack[++top]=x;

}int main(){

scanf("%d%d",&n,&b);

for(int i=1;i點我進入ac通道

bzoj1086 王室聯邦

給出一棵樹,求一種分塊方案,使得每個塊的大小 size in b,3b 每個塊還要選乙個省會,省會可以在塊外,但是省會到塊內任何乙個點路徑上的所有除了省會的點都必須屬於這個塊。n le 1000 一次dfs即可解決。做法如下 實現中有乙個問題,對於乙個兒子,它在棧中積累了不到 b 個點,而在下乙個搜...

BZOJ 1086 王室聯邦

思路 貪心,每次當儲存的兒子大於等於b時,分出乙個塊,這樣每次每個塊至多為2b,這樣剩下的沒有被分的塊小於b,可以加入任意乙個塊,都是合法的。1 include2 include3 include4 include5 include6 int tot,go 200005 first 200005 n...

王室聯邦(bzoj 1086)

餘 人國的國王想重新編制他的國家。他想把他的國家劃分成若干個省,每個省都由他們王室聯邦的乙個成 員來管理。他的國家有n個城市,編號為1.n。一些城市之間有道路相連,任意兩個不同的城市之間有且僅有一條 直接或間接的道路。為了防止管理太過分散,每個省至少要有b個城市,為了能有效的管理,每個省最多只有3b...