1. 程式人生 > >bzoj1086: [SCOI2005]王室聯邦

bzoj1086: [SCOI2005]王室聯邦

fine nbsp 管理 define 如果 font sca cap scoi2005

Description

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

Input

  第一行包含兩個數N,B(1<=N<=1000, 1 <= B <= N)。接下來N-1行,每行描述一條邊,包含兩個數,即這
條邊連接的兩個城市的編號。

Output

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

Sample Input

8 2
1 2
2 3
1 8
8 7
8 6
4 6
6 5

Sample Output

3
2 1 1 3 3 3 3 2
2 1 8
題解 首先無根樹轉有根樹,然後往下找葉子,回溯的時候判斷一下是否達到成省標準,達到了就劃成一個省,把根作為省會,最後一塊隨便扔到哪個省就行了(因為每一個省都是達到m個就劃出去,所以最後一塊隨便放在哪個省裏都不會超過3m個)

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 #define maxn 1005
 5 using namespace std;
 6 int sta[maxn],size[maxn],map[maxn][maxn],cap[maxn],belong[maxn],n,m,top,pro;
 7 void dfs(int u,int fa)
 8 {
 9     sta[++top]=u;
10     for(int i=1; i<=n ; ++i)
11         if
(map[u][i]) 12 { 13 if(i==fa)continue; 14 dfs(i,u); 15 if(size[u]+size[i]>=m) 16 { 17 size[u]=0; 18 cap[++pro]=u; 19 while(sta[top]!=u)belong[sta[top--]]=pro; 20 } 21 else size[u]+=size[i]; 22 } 23 size[u]++; 24 } 25 void dolast(int u,int fa,int c) 26 { 27 if(belong[u])return ; 28 belong[u]=c; 29 for(int i=1 ; i<=n ; ++i ) 30 if(map[u][i]) 31 if(i!=fa) 32 dolast(i,u,c); 33 } 34 int main() 35 { 36 int u,v; 37 scanf("%d%d",&n,&m); 38 if(m>n) 39 { 40 printf("0"); 41 return 0; 42 } 43 for(int i=1; i<n ; ++i) 44 { 45 scanf("%d%d",&u,&v); 46 map[u][v]=map[v][u]=1; 47 } 48 dfs(1,0); 49 if(!pro)cap[++pro]=1; 50 dolast(1,0,pro); 51 printf("%d\n",pro); 52 for(int i=1 ; i<=n ; ++i )printf("%d ",belong[i]); 53 printf("\n"); 54 for(int i=1 ; i<=pro ; ++i)printf("%d ",cap[i]); 55 return 0; 56 }

bzoj1086: [SCOI2005]王室聯邦