【BZOJ】【1086】 【SCOI2005】王室联邦
樹分塊
orz vfk && PoPoQQQ
http://vfleaking.blog.163.com/blog/static/174807634201231684436977/ http://blog.csdn.net/popoqqq/article/details/42772237這題是要把樹分成一塊一塊的……(感覺好像不是原來理解的樹分塊處理操作啊……)
每塊大小B<= size <=3B ,一種簡單粗暴的想法就是dfs,每找到B個就分一塊,但是這樣連通性不能保證(一顆子樹的下半截和另一棵子樹的上半截組成一塊)。所以我們就想:能不能從底部往上組塊,每棵子樹較深的部分自己成塊,然后靠近根的部分組成一個大塊
這樣就可以保證連通性和塊大小不會超了,最后dfs結束后肯定還會有剩余的未組成塊的節點,把它們歸到最后一個塊就可以了。證明看vfk博客就行……
至于實現這個“等待序列”,用的是PoPoQQQ的方法:用棧來實現,對當前節點x,它的等待序列就是bottom--top(bottom初始化為top,然后再向棧里加的元素就是他的兒子)……呃……這個自己手畫一個簡單的就能理解了吧……?或者腦補一下……嗯
1 /************************************************************** 2 Problem: 1086 3 User: Tunix 4 Language: C++ 5 Result: Accepted 6 Time:12 ms 7 Memory:1320 kb 8 ****************************************************************/ 9 10 //BZOJ 1086 11 #include<cstdio> 12 #include<cstring> 13 #include<cstdlib> 14 #include<iostream> 15 #include<algorithm> 16 #define rep(i,n) for(int i=0;i<n;++i) 17 #define F(i,j,n) for(int i=j;i<=n;++i) 18 #define D(i,j,n) for(int i=j;i>=n;--i) 19 using namespace std; 20 void read(int &v){ 21 v=0; int sign=1; char ch=getchar(); 22 while(ch<'0'||ch>'9'){ if (ch=='-') sign=-1; ch=getchar();} 23 while(ch>='0'&&ch<='9'){ v=v*10+ch-'0'; ch=getchar();} 24 v*=sign; 25 } 26 /******************tamplate*********************/ 27 const int N=2015; 28 int head[N],to[N],next[N],cnt; 29 void add(int x,int y){ 30 to[++cnt]=y; next[cnt]=head[x]; head[x]=cnt; 31 to[++cnt]=x; next[cnt]=head[y]; head[y]=cnt; 32 } 33 /********************edge***********************/ 34 int n,B,K; 35 int st[N],top; 36 int belong[N],root[N],tot; 37 void dfs(int x,int fa){ 38 int bottom=top; 39 for(int i=head[x];i;i=next[i]) 40 if (to[i]!=fa){ 41 dfs(to[i],x); 42 if (top-bottom>=B){ 43 root[++tot]=x; 44 while(top!=bottom) 45 belong[st[top--]]=tot; 46 } 47 } 48 st[++top]=x; 49 } 50 51 int main(){ 52 read(n); read(B); 53 int x,y; 54 F(i,2,n){ 55 read(x); read(y); 56 add(x,y); 57 } 58 dfs(1,0); 59 while(top) belong[st[top--]]=tot; 60 printf("%d\n",tot); 61 F(i,1,n) printf("%d ",belong[i]); 62 printf("\n"); 63 F(i,1,tot) printf("%d ",root[i]); 64 return 0; 65 } View Code?
1086: [SCOI2005]王室聯邦
Time Limit: 10 Sec??Memory Limit: 162 MBSec??Special JudgeSubmit: 752??Solved: 416
[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
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
HINT
Source
[Submit][Status][Discuss]轉載于:https://www.cnblogs.com/Tunix/p/4247955.html
總結
以上是生活随笔為你收集整理的【BZOJ】【1086】 【SCOI2005】王室联邦的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ARX中实现实体的偏移
- 下一篇: 用parsetInt解析数字,并求和