題意:國王想把他的國家劃分成若干個省。他的國家有n個城市,是一棵樹,即n-1條邊,編號為1..n。為了防止管理太過分散,每個省至少要有b個城市,為了能有效的管理,每個省最多只有3b個城市。每個省必須有乙個省會,這個省會可以位於省內,也可以在該省外。但是該省的任意乙個城市到達省會所經過的道路上的城市(除了最後乙個城市,即該省省會)都必須屬於該省。乙個城市可以作為多個省的省會。輸出有多少個省會,每個城市屬於哪個省會,每個省的省會。
思路:暫時先不管省會應該在哪的問題,其實就是要對樹進行分塊,每塊必須有b~3b的點。
那麼如何分塊?按常理,只要搜尋滿b個點就立刻進行組塊,而且塊中的點最好是連通的,如若不巧,非連通,一會再說,能解決。由於要盡量使得所分的塊是連通的,那麼可以用dfs的回溯,將回溯過程收集的點裝進stack,一般來說,任意乙個點為根的子樹中的所有點都是在stack中是連在一塊的(因為先收集完孩子才會收集到自己,所以這是肯定的)。
收集完這個回溯序列有什麼用?分塊其實可以從裡面分出來,只是不能隨便就按照b個點就分一塊,這樣子可能會不連通。但是可以利用「以任意一點為根的子樹中所有點在stack中肯定是相連的」這個特點,如果遍歷到某個點x,它的某1個分叉中的點已經夠b個了,那就組成一塊;如果這一分叉不夠b個,那麼可以跟另一分叉組成一塊,這樣子雖然是不連通的,但是沒有關係,只要省會設定在當前點x,不就連通了?不夠點數的分叉都是可以組成1塊,注意將一棵子樹遍歷完了,才能考慮將這個子樹中的點分塊。
如果stack中仍有剩下的點,肯定是不足b個,那麼可以全部歸到最後乙個塊中,必定不超過3b個點。
1 #include 2ac**#define pii pair3
#define inf 0x3f3f3f3f
4#define ll long long
5using
namespace
std;
6const
int n=1010;7
8 vectorvect[n];
9int
n, m;
1011
void add_edge(int
from,int
to)12
1617 stackstac;
18int
belongto[n], vis[n], block, pro[n];
19void dfs(int x) //
num表示後面還剩下幾個。
2040}41
}42}43
stac.push(x);44}
4546
4748
intmain()
4962
63 dfs(1);//
從任意點遍歷
64while(!stac.empty()) //
可能有餘下的點
6570
if(n"
0\n");//
不夠1塊
71else
7279}80
81return0;
82 }
bzoj1086 王室聯邦
給出一棵樹,求一種分塊方案,使得每個塊的大小 size in b,3b 每個塊還要選乙個省會,省會可以在塊外,但是省會到塊內任何乙個點路徑上的所有除了省會的點都必須屬於這個塊。n le 1000 一次dfs即可解決。做法如下 實現中有乙個問題,對於乙個兒子,它在棧中積累了不到 b 個點,而在下乙個搜...
bzoj 1086 王室聯邦
餘 人國的國王想重新編制他的國家。他想把他的國家劃分成若干個省,每個省都由他們王室聯邦的乙個成員來管理。他的國家有n個城市,編號為1.n。一些城市之間有道路相連,任意兩個不同的城市之間有且僅有一條直接或間接的道路。為了防止管理太過分散,每個省至少要有b個城市,為了能有效的管理,每個省最多只有3b個城...
BZOJ 1086 王室聯邦
思路 貪心,每次當儲存的兒子大於等於b時,分出乙個塊,這樣每次每個塊至多為2b,這樣剩下的沒有被分的塊小於b,可以加入任意乙個塊,都是合法的。1 include2 include3 include4 include5 include6 int tot,go 200005 first 200005 n...