1086: [SCOI2005]王室聯邦
Time Limit: 10 Sec Memory Limit: 162 MBSec Special JudgeSubmit: 826 Solved: 471
[Submit][Status][Discuss]
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
1 2
2 3
1 8
8 7
8 6
4 6
6 5
Sample Output
2 1 1 3 3 3 3 2
2 1 8
因此我們在每次進入遞歸時維護一個棧底,對於當前子樹來說這個棧底就是整個棧的底,棧底以下的元素不能修改或彈棧
這樣當一棵子樹深搜過後由於子樹內未分塊節點不超過b,之前搜過的未分塊節點數也不超過b,因此每塊不超過2b
那麼題目爲什麼給了3b呢?
深搜結束後可能會剩餘一些節點,這些節點的數量不超過b,而且一定與當前分出的最後一塊連通
因此我們將剩餘節點分到最後一塊中,可以保證最後一塊的大小不超過3b
1 #include<cstdio> 2 #include<cstring> 3 #include<cmath> 4 #include<algorithm> 5 6 #define maxn 1001 7 8 using namespace std; 9 10 inline int in() 11 { 12 int x=0;char ch=getchar(); 13 while(ch<'0'||ch>'9')ch=getchar(); 14 while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar(); 15 return x; 16 } 17 18 int n,l,last[maxn],tot=0,sta[maxn],top=0,father[maxn],root[maxn],cnt=0; 19 20 struct ed{ 21 int to,last; 22 }edge[maxn*2]; 23 24 void add(int u,int v) 25 { 26 edge[++tot].to=v,edge[tot].last=last[u],last[u]=tot; 27 edge[++tot].to=u,edge[tot].last=last[v],last[v]=tot; 28 } 29 30 void dfs(int poi,int Last) 31 { 32 int lim=top; 33 for(int i=last[poi];i;i=edge[i].last)if(edge[i].to!=Last){ 34 dfs(edge[i].to,poi); 35 if(top-lim>=l) 36 { 37 root[++cnt]=poi; 38 while(top!=lim)father[sta[top--]]=cnt; 39 } 40 } 41 sta[++top]=poi; 42 } 43 44 int main() 45 { 46 int u,v; 47 n=in();l=in(); 48 for(int i=1;i<n;i++) 49 u=in(),v=in(),add(u,v); 50 dfs(1,0); 51 while(top)father[sta[top--]]=cnt; 52 printf("%d\n",cnt); 53 for(int i=1;i<=n;i++)printf("%d ",father[i]); 54 printf("\n"); 55 for(int i=1;i<=cnt;i++)printf("%d ",root[i]); 56 return 0; 57 }