您的位置:首页 > 其它

【BZOJ】1086 王室联邦

2016-01-23 09:42 661 查看
【题意】

给定NN个点的一棵树,要求将点划分成多个块,每个块BB满足存在至少一个点capcap,使得∀i∈B\forall i\in B,ii到capcap的路径上的点集(Path(i,cap)∖{cap})⊂B(Path(i,cap)\setminus\lbrace cap\rbrace)\subset B。

【数据范围】1≤B≤N≤10001\leq B\leq N\leq 1000

【分析】

据说这就是把树分块的算法。

然而我是想看强制在线莫队才看这题的。

本题题解链接:

http://vfleaking.blog.163.com/blog/static/174807634201231684436977/)

时间复杂度:O(n)O(n)

空间复杂度:O(n)O(n)

【代码】

#include <cstdio>
#include <cctype>

const int N=1024;

int n,B;
struct Graph
{
int v,nxt;
}mp[N<<1];
int tt,hd
;

inline int read(void)
{
int x=0,f=1; char c=getchar();
for (;!isdigit(c);c=getchar()) if (c=='-') f=-1;
for (;isdigit(c);c=getchar()) x=x*10+c-'0';
return x*f;
}

inline void ins(int u,int v)
{
mp[++tt].v=v;
mp[tt].nxt=hd[u];
hd[u]=tt;
}

void init(void)
{
int u,v;
n=read(),B=read();
for (int i=1;i<n;i++)
{
u=read(),v=read();
ins(u,v),ins(v,u);
}
}

int stk
,top;
int vis
;
int own
,cap
,col;

void dfs(int now)
{
int bot=top;
vis[now]=1;
for (int k=hd[now];k;k=mp[k].nxt)
if (!vis[mp[k].v])
{
dfs(mp[k].v);
if (top-bot>=B)
{
cap[++col]=now;
for (;top!=bot;own[stk[top--]]=col);
}
}
stk[++top]=now;
}

void work(void)
{
dfs(1);
for (;top;own[stk[top--]]=col);
printf("%d\n",col);
for (int i=1;i<n;i++) printf("%d ",own[i]); printf("%d\n",own
);
for (int i=1;i<col;i++) printf("%d ",cap[i]); printf("%d\n",cap[col]);
}

int main(void)
{
init();
work();
return 0;
}


【小结】树分块的方法。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: