bzoj1086[SCOI2005]王室联邦
傳送門(mén)
Description
“余”人國(guó)的國(guó)王想重新編制他的國(guó)家。他想把他的國(guó)家劃分成若干個(gè)省,每個(gè)省都由他們王室聯(lián)邦的一個(gè)成
員來(lái)管理。他的國(guó)家有n個(gè)城市,編號(hào)為1..n。一些城市之間有道路相連,任意兩個(gè)不同的城市之間有且僅有一條
直接或間接的道路。為了防止管理太過(guò)分散,每個(gè)省至少要有B個(gè)城市,為了能有效的管理,每個(gè)省最多只有3B個(gè)
城市。每個(gè)省必須有一個(gè)省會(huì),這個(gè)省會(huì)可以位于省內(nèi),也可以在該省外。但是該省的任意一個(gè)城市到達(dá)省會(huì)所經(jīng)
過(guò)的道路上的城市(除了最后一個(gè)城市,即該省省會(huì))都必須屬于該省。一個(gè)城市可以作為多個(gè)省的省會(huì)。聰明的
你快幫幫這個(gè)國(guó)王吧!
Input
第一行包含兩個(gè)數(shù)N,B(1<=N<=1000, 1 <= B <= N)。接下來(lái)N-1行,每行描述一條邊,包含兩個(gè)數(shù),即這
條邊連接的兩個(gè)城市的編號(hào)。
Output
如果無(wú)法滿足國(guó)王的要求,輸出0。否則輸出數(shù)K,表示你給出的劃分方案中省的個(gè)數(shù),編號(hào)為1..K。第二行輸
出N個(gè)數(shù),第I個(gè)數(shù)表示編號(hào)為I的城市屬于的省的編號(hào),第三行輸出K個(gè)數(shù),表示這K個(gè)省的省會(huì)的城市編號(hào),如果
有多種方案,你可以輸出任意一種。
Sample Input
8 21 2
2 3
1 8
8 7
8 6
4 6
6 5
Sample Output
32 1 1 3 3 3 3 2
2 1 8
題解
如果有一顆子樹(shù),我們把它上面的點(diǎn)劃分到一個(gè)省以內(nèi),那么省會(huì)一定是這個(gè)子樹(shù)上的點(diǎn)或者子樹(shù)的根節(jié)點(diǎn)的父親節(jié)點(diǎn)。那么我們可以判斷出除非n<b,否則題目一定有解。因此我們考慮對(duì)其分塊,用一個(gè)棧維護(hù)。從根節(jié)點(diǎn)向下dfs,每次向棧中壓入當(dāng)前訪問(wèn)的值。每當(dāng)子樹(shù)大小大于b時(shí),就將其記錄成一塊,根為省會(huì)。最后一定剩下不到b個(gè)節(jié)點(diǎn),我們分的每一塊的大小一定大于等于b且小于2b。所以我們把剩下的節(jié)點(diǎn)全部丟到最后一塊中,就可以求出一個(gè)解了。
代碼
1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<algorithm> 5 #include<cmath> 6 using namespace std; 7 int ans=0,n,cnt=1,t=0,b; 8 struct node{ 9 int to,nxt; 10 }e[10010]; 11 int head[1010],bel[1010],mas[1010],sta[2010]; 12 void add(int u,int v){ 13 e[++cnt].to=v;e[cnt].nxt=head[u];head[u]=cnt; 14 e[++cnt].to=u;e[cnt].nxt=head[v];head[v]=cnt; 15 } 16 void dfs(int x,int fa){ 17 int now=t; 18 int i; 19 for(i=head[x];i;i=e[i].nxt){ 20 if(e[i].to!=fa){ 21 dfs(e[i].to,x); 22 if(t-now>=b){ 23 mas[++ans]=x; 24 while(t!=now){ 25 bel[sta[t--]]=ans; 26 } 27 } 28 } 29 } 30 sta[++t]=x; 31 } 32 int main(){ 33 scanf("%d%d",&n,&b); 34 if(n<b){ 35 printf("0\n");return 0; 36 } 37 int i,j,x,y; 38 for(i=1;i<n;++i){ 39 scanf("%d%d",&x,&y); 40 add(x,y); 41 } 42 dfs(1,0); 43 while(t) bel[sta[t--]]=ans; 44 printf("%d\n",ans); 45 if(ans==0) return 0; 46 for(i=1;i<=n;++i){ 47 printf("%d ",bel[i]); 48 } 49 printf("\n"); 50 for(i=1;i<=ans;++i) printf("%d ",mas[i]); 51 printf("\n"); 52 return 0; 53 }?
轉(zhuǎn)載于:https://www.cnblogs.com/lazytear/p/9080371.html
總結(jié)
以上是生活随笔為你收集整理的bzoj1086[SCOI2005]王室联邦的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 14亿分钟等于多少年?
- 下一篇: 期转现是指什么