「日常訓練與知識學習」樹的分塊(王室聯邦,HYSBZ-1086)
阿新 • • 發佈:2018-11-13
題意與分析
這題的題意就是樹分塊,更具體的看題目(中文題)。
學習這一題是為了樹的分塊,為樹上莫隊做鋪墊。
參考1:https://blog.csdn.net/LJH_KOQI/article/details/52326103
參考2:https://blog.csdn.net/popoqqq/article/details/42772237
注意到題目要求某塊區域所有的點到根的路徑上的點都屬於該區域。因此不能夠暴力地去dfs,每找到\(B\)個分一塊是不可取的,因為無法保證聯通性(一顆子樹的下半截和另一棵子樹的上半截組成一塊)。因此,我們需要儘可能地從底部往上去組織塊(Block),“每棵子樹較深的部分自己成塊,然後靠近根的部分組成一個大塊”。
因此這麼做:對於一個點\(x\)
程式碼
/* * Filename: hysbz1086.cpp * Date: 2018-11-13 */ #include <bits/stdc++.h> #define INF 0x3f3f3f3f #define PB push_back #define MP make_pair #define fi first #define se second #define rep(i,a,b) for(repType i=(a); i<=(b); ++i) #define per(i,a,b) for(repType i=(a); i>=(b); --i) #define ZERO(x) memset(x, 0, sizeof(x)) #define MS(x,y) memset(x, y, sizeof(x)) #define ALL(x) (x).begin(), (x).end() #define QUICKIO \ ios::sync_with_stdio(false); \ cin.tie(0); \ cout.tie(0); #define DEBUG(...) fprintf(stderr, __VA_ARGS__), fflush(stderr) using namespace std; typedef long long ll; typedef int repType; const int MAXN=1005; vector<int> G[MAXN]; int stk[MAXN],top=0; int root[MAXN],cnt=0; int belong[MAXN]; int n,b; void dfs(int now, int pre) { int bottom=top; rep(i,0,int(G[now].size())-1) if(G[now][i]!=pre) { dfs(G[now][i],now); if(top-bottom>=b) { root[++cnt]=now; while(top!=bottom) belong[stk[top--]]=cnt; } } stk[++top]=now; } int main() { QUICKIO cin>>n>>b; rep(i,1,n-1) { int u,v; cin>>u>>v; G[u].PB(v); G[v].PB(u); } dfs(1,0); while(top) // the last block belong[stk[top--]]=cnt; cout<<cnt<<endl; rep(i,1,n) cout<<belong[i]<<char(i==n?'\n':' '); rep(i,1,cnt) cout<<root[i]<<char(i==cnt?'\n':' '); return 0; }