BZOJ1086 SCOI2005 王室聯邦

2022-05-19 21:57:55 字數 1258 閱讀 3641

給出n個點,n-1條邊,將這n個點分成若干個部分,每個部分都有乙個中心,給出b,要求2b>=每個部分的點數》=b,是每個部分中的任意乙個點到達中心所經過的點(除了最後乙個點,即該部分的中心點)都必須屬於該部分,求出是否能滿足將n個點都分成若干個部分

既然題目要求該區域所有的點到根的路徑上的點都屬於該區域。很明顯,就是一棵樹,所以題意其實就是把一棵多叉樹分成若干個區域,然而又不用輸出最小方案,所以弱爆了。這個玩意我也不知道它算什麼,應該屬於dfs的範疇吧。 

一種簡單粗暴的想法就是dfs,每找到b個就分一塊,但是這樣連通性不能保證(一顆子樹的下半截和另一棵子樹的上半截組成一塊)。所以我們就想:能不能從底部往上組塊,每棵子樹較深的部分自己成塊,然後靠近根的部分組成乙個大塊。 

所以我們這麼做:對於乙個點x,以初次訪問它時,棧的棧頂作為相對棧底,每遍歷完它的乙個子節點所在的子樹,判斷此時棧頂-相對棧底得到的元素個數是否大於或等於b,若成立,那麼彈棧至相對棧頂。當訪問完所有子節點要回溯到x的父節點時,把x壓入棧。 

這樣就可以保證連通性和塊大小不會超了,最後dfs結束後肯定還會有剩餘的未組成塊的節點,把它們歸到最後乙個塊就可以了。

#include#include

using

namespace

std;

struct

node

a[2100];int len,last[1100

];void ins(int x,int

y)int sta[1100

],top;

int belong[1100

],tot;

int rt[1100

],n,b;

void dfs(int fa,int

x) }}}

sta[++top]=x;

}int

main()

for(int i=1;i)

dfs(

0,1);

while(top) belong[sta[top--]]=tot;

printf(

"%d\n

",tot);

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

%d "

,belong[i]);

printf("\n

");for(int i=1;i<=tot;i++)printf("

%d "

,rt[i]);

printf("\n

");return0;

}

bzoj1086 scoi2005 王室聯邦

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

bzoj1086 SCOI2005 王室聯邦

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

BZOJ 1086 SCOI2005 王室聯邦

啊啊啊啊啊啊啊啊啊啊啊啊 又是一道赤果果的水水模板題 沒辦法啊我太弱了。好吧 這是一道樹分塊 原題戳對其實你們依然不用戳 餘 人國的國王想重新編制他的國家。他想把他的國家劃分成若干個省,每個省都由他們王室聯邦的乙個成 員來管理。他的國家有n個城市,編號為1.n。一些城市之間有道路相連,任意兩個不同的...