HDOJ3887-DFS人工栈,树状数组
来源:互联网 发布:软件企业认定 招标 编辑:程序博客网 时间:2024/04/30 02:27
/* 树状数组。dfs过程中,进入一个节点x前求一次sum(x-1),然后add操作,递归返回节点x后再求一次sum(x-1) 两次sum操作的差值就是比x小的个数 本题数据量大,递归太深可能爆栈,一般用while+人工栈模拟递归的过程,当然c++可以设置栈的大小,这样就不会爆栈了我不告诉你思路是看来的~~可取的是人工栈过了一遍。*/ #include <cstdio>#include <cstring>#include <iostream>#include <vector>using namespace std;const int NN=100010;vector<int> v[NN];int n,r;int s[NN],c[NN],cur[NN],pre[NN];bool vis[NN];int lowbit(int x){ return x&(-x);}void update(int x,int w){ while (x<=n) { c[x]+=w; x+=lowbit(x); }}int getsum(int x){ int ret=0; while (x) { ret+=c[x]; x-=lowbit(x); } return ret;}int ss[NN],top;void dfs(){ ss[top=1]=r; pre[r]=0; vis[r]=true; update(r,1); while (top) { int x=ss[top]; for (int &i=cur[x]; i<v[x].size(); i++) { int y=v[x][i]; if (!vis[y]) { vis[y]=true; pre[y]=getsum(y-1); update(y,1); ss[++top]=y; break; } } if (cur[x]==v[x].size()) { s[x]=getsum(x-1)-pre[x]; top--; } }}int main(){ while (scanf("%d%d",&n,&r)!=EOF && n|r) { for (int i=1; i<=n; i++) { v[i].clear(); c[i]=0; s[i]=0; vis[i]=false; cur[i]=0; } int x,y; for (int i=1; i<n; i++) { scanf("%d%d",&x,&y); v[x].push_back(y); v[y].push_back(x); } dfs(); printf("%d",s[1]); for (int i=2; i<=n; i++) printf(" %d",s[i]); printf("\n"); } return 0;}