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

Bzoj 1086: [SCOI2005]王室聯邦

把他 聯邦 pen href == for stream ems bbs

1086: [SCOI2005]王室聯邦

Time Limit: 10 Sec Memory Limit: 162 MBSec Special Judge
Submit: 1900 Solved: 1160
[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 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

HINT

Source

非常簡單的樹分塊,為了學莫隊上樹專門學學樹分塊

慕名來做這個題

#include<iostream>
#include<cstdio>
using namespace std;
#define maxn 1010
int n,B,cnt,head[maxn<<1
],num; typedef int exint[maxn]; exint sz,belong,cap; bool vis[maxn]; struct node{ int to,pre; }e[maxn<<1]; void Insert(int from,int to){ e[++num].to=to; e[num].pre=head[from]; head[from]=num; } void Cola(int pre,int now){ for(int i=head[now];i;i=e[i].pre){ int to=e[i].to; if(to==pre||vis[to]==0||belong[to])continue; belong[to]=cnt; Cola(now,to); } } void dfs(int pre,int now){ vis[now]=1; for(int i=head[now];i;i=e[i].pre){ int to=e[i].to; if(to==pre)continue; dfs(now,to); sz[now]+=sz[to]; if(sz[now]>=B){ cnt++; Cola(pre,now); cap[cnt]=now; sz[now]=0; } }sz[now]++; } int main(){ freopen("Cola.txt","r",stdin); scanf("%d%d",&n,&B); int a,b; for(int i=1;i<n;i++){ scanf("%d%d",&a,&b); Insert(a,b);Insert(b,a); } dfs(0,1); printf("%d\n",cnt); for(int i=1;i<=n;i++){ printf("%d ",belong[i]>0?belong[i]:cnt); }printf("\n"); for(int i=1;i<=cnt;i++){ printf("%d ",cap[i]); } }

Bzoj 1086: [SCOI2005]王室聯邦