BZOJ 1086 SCOI2005 王室聯邦

2021-08-04 10:05:57 字數 1878 閱讀 2994

啊啊啊啊啊啊啊啊啊啊啊啊

又是一道赤果果的水水模板題

沒辦法啊我太弱了。。。

好吧 這是一道樹分塊

原題戳對其實你們依然不用戳

「餘」人國的國王想重新編制他的國家。他想把他的國家劃分成若干個省,每個省都由他們王室聯邦的乙個成

員來管理。他的國家有n個城市,編號為1..n。一些城市之間有道路相連,任意兩個不同的城市之間有且僅有一條

直接或間接的道路。為了防止管理太過分散,每個省至少要有b個城市,為了能有效的管理,每個省最多只有3b個

城市。每個省必須有乙個省會,這個省會可以位於省內,也可以在該省外。但是該省的任意乙個城市到達省會所經

過的道路上的城市(除了最後乙個城市,即該省省會)都必須屬於該省。乙個城市可以作為多個省的省會。聰明的

你快幫幫這個國王吧!

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

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

如果無法滿足國王的要求,輸出0。否則輸出數k,表示你給出的劃分方案中省的個數,編號為1..k。第二行輸

出n個數,第i個數表示編號為i的城市屬於的省的編號,第三行輸出k個數,表示這k個省的省會的城市編號,如果

有多種方案,你可以輸出任意一種。

8 2

1 2

2 3

1 8

8 7

8 6

4 6

6 5

3 2 1 1 3 3 3 3 2

2 1 8

惹。。。

樹分塊啊。。。

思想特別簡單。。。

就是把樹分成塊塊啊。。。

關鍵在於怎麼分這些塊塊,不至於太碎(就是保證其連通性)

dfs序啊!!!維護乙個棧啊!!!

並不是乙個實用的演算法

所以我們這麼做:對於乙個點x,以初次訪問它時,棧的棧頂作為相對棧底,每遍歷完它的乙個子節點所在的子樹,判斷此時棧頂-相對棧底得到的元素個數是否大於或等於b,若成立,那麼彈棧至相對棧頂。當訪問完所有子節點要回溯到x的父節點時,把x壓入棧。稍微想一下就可以明白這樣可以保證分出的塊內的元素的合理性。

最後的棧中還會剩很多點,但是不會超過b,而我們分的塊的大小也不會超過2b(自行腦補),所以把棧裡的所有點扔到最後一塊裡,大小不會超過3b,正好對應題中的要求。

複雜度與b有關

ac**:(當時沒看見special judge。。。是個人都能想到啊。。。然而我是豬)

#include

#define maxn 1005

using namespace std;

int n,b;

int head[maxn],tot=1,root[maxn],belong[maxn],top,cnt,stk[maxn];

struct nodee[2

*maxn];

void add(int u,int v)

void dfs(int u,int father)

}stk[++top]=u;

}int main()

dfs(1,-1);

while(top)

belong[stk[top--]]=cnt;

printf("%d\n",cnt);

for(int i=1;i<=n;i++)

printf("%d

%c",belong[i],i==n?'\n':' ');

for(int i=1;i<=cnt;i++)

printf("%d

%c",root[i],i==cnt?'\n':' ');

return

0;}

bzoj1086 scoi2005 王室聯邦

題目鏈結 本來是來學樹上分塊的,沒想到正解是貪心 dfs。題意 求將樹分為幾個聯通塊,每個聯通塊大小大於b小於3b,是否可行。solution1 題都沒看就翻了題解。發現時貪心 dfs。一遍dfs即可。注意到以x為根節點時,其兒子s,則子樹s中與s相連的節點的連通塊,如果要構成乙個省,既可以s作為省...

bzoj1086 SCOI2005 王室聯邦

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

BZOJ 1086 SCOI2005 王室聯邦

對一棵樹進行分塊。dfs,找到了乙個節點,記錄乙個陣列st s t,代表它和它的子樹中,沒有被劃分進任何省的點。首先對他的每個節點dfs,把它兒子的st s t序列加入自己的,如果自己st s t序列大於了 b b 就把這所有的點都划進乙個省裡面,省會是當前dfs到的這個節點。最後再把自己加入st ...