标签:大小 fir include c代码 scoi2005 方式 inline printf std
利用了树上莫队的分块方式,保证每个块的大小都\(\ge\)B且$\le$3B,然后证明略过
仅叙述一下算法的过程
使用一个栈,依次dfs这个点的每个子树,如果发现新增的节点数大于等于B,就分出新的一块,
最后把剩下的节点塞进最后一个块里
void dfs(int u,int f){
int t=S.size();
for(int i=fir[u];i;i=nxt[i]){
if(v[i]==f)
continue;
dfs(v[i],u);
if(S.size()-t>=B){
++block_cnt;
core[block_cnt]=u;
while(S.size()>t){
belong[S.top()]=block_cnt;
S.pop();
}
}
}
S.push(u);
}
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <stack>
using namespace std;
stack<int> S;
int v[5000],fir[5000],nxt[5000],cnt,B,n,core[5000],block_cnt=0,belong[5000];
void addedge(int ui,int vi){
++cnt;
v[cnt]=vi;
nxt[cnt]=fir[ui];
fir[ui]=cnt;
}
void dfs(int u,int f){
int t=S.size();
for(int i=fir[u];i;i=nxt[i]){
if(v[i]==f)
continue;
dfs(v[i],u);
if(S.size()-t>=B){
++block_cnt;
core[block_cnt]=u;
while(S.size()>t){
belong[S.top()]=block_cnt;
S.pop();
}
}
}
S.push(u);
}
int main(){
scanf("%d %d",&n,&B);
for(int i=1;i<n;i++){
int a,b;
scanf("%d %d",&a,&b);
addedge(a,b);
addedge(b,a);
}
dfs(1,0);
while(!S.empty()){
belong[S.top()]=block_cnt;
S.pop();
}
printf("%d\n",block_cnt);
for(int i=1;i<=n;i++)
printf("%d ",belong[i]);
printf("\n");
for(int i=1;i<=block_cnt;i++)
printf("%d ",core[i]);
printf("\n");
return 0;
}
标签:大小 fir include c代码 scoi2005 方式 inline printf std
原文地址:https://www.cnblogs.com/dreagonm/p/10817707.html