1 条题解
-
0
C++ :
#include<cstdio> #include<vector> #include<queue> #include<cstring> #include<cmath> #include<algorithm> #include<iostream> using namespace std; vector<int> a[100001],shi[100001],son[100001]; queue<int> ling; int ru[100001],fa[100001][20],deep[100001],ans[100001]; int LCA(int aa,int bb)//用倍增法求LCA { if(deep[aa]>deep[bb]) swap(aa,bb); int ff=deep[bb]-deep[aa]; for(int i=0;(1<<i)<=ff;i++) if((1<<i)&ff) bb=fa[bb][i]; if(aa!=bb) { for(int i=18;i>=0;i--) if(fa[aa][i]!=fa[bb][i]) { aa=fa[aa][i]; bb=fa[bb][i]; } aa=fa[aa][0]; } return aa; } void dfs(int o)//树上前缀和 { if(son[o].empty()) {ans[o]=1;return;} for(int i=0;i<son[o].size();i++) { if(ans[son[o][i]]==0) dfs(son[o][i]); ans[o]+=ans[son[o][i]]; } ans[o]++; } int main() { int n; cin>>n; memset(ru,0,sizeof(ru)); for(int i=1;i<=n;i++) { int x; scanf("%d",&x); while(x!=0) { a[x].push_back(i); ru[i]++; shi[i].push_back(x); scanf("%d",&x); } } memset(fa,0,sizeof(fa)); memset(deep,0,sizeof(deep)); deep[70000]=1; for(int i=1;i<=n;i++) if(ru[i]==0) { ling.push(i); shi[i].push_back(70000); } while(!ling.empty())//拓扑排序(同时加点) { int yu=ling.front(); ling.pop(); int lca=shi[yu][0]; if(shi[yu].size()!=1) for(int i=1;i<shi[yu].size();i++) lca=LCA(lca,shi[yu][i]);//把每个节点都连接在它的所有食物的LCA上 deep[yu]=deep[lca]+1;//新加入节点的深度 fa[yu][0]=lca; son[lca].push_back(yu); for(int i=1;i<=18;i++)//更新新加入节点的倍增数组 if(fa[yu][i-1]) fa[yu][i]=fa[fa[yu][i-1]][i-1]; for(int i=0;i<a[yu].size();i++) { ru[a[yu][i]]--; if(ru[a[yu][i]]==0) ling.push(a[yu][i]); } } memset(ans,0,sizeof(ans)); dfs(70000);//求树上前缀和 for(int i=1;i<=n;i++) cout<<(ans[i]-1)<<endl; return 0; }
- 1
信息
- ID
- 976
- 时间
- 1000ms
- 内存
- 128MiB
- 难度
- (无)
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者