//如何求树上任意一点为根的dp值
//将以此点将树划分成两部分,一部分还是原来的子树
//另一部分是此点的父亲往上为子树,这一点的转化很巧妙,一次从上到下的dp即可。
//R[i]记录此点右面子树的乘积,从右到左,其实在最右的时候up[父亲]就已经计算了父亲往上的值了。现在只要记录兄弟即可。
import java.io.*;
import java.util.*;
public class cf {
FastScanner in;
final int INF=0x3fffffff;
final int N=200010;
final long mod = 1000000007;
edge[] e;
int[] head;
int cnt;
long[] dp;
long []L,R;
long[] ans,up;
int temp[]=new int[N];
void addedge(int u,int v){
e[cnt]=new edge();
e[cnt].from=u;e[cnt].to=v;
e[cnt].next=head[u];head[u]=cnt++;
}
void DP(int u,int p){
dp[u]=1;
for(int i=head[u];i!=-1;i=e[i].next){
int v=e[i].to;
if(p==v)continue;
DP(v,u);
dp[u]*=(dp[v]+1);
dp[u]%=mod;
}
}
void DFS(int u,int p){//相当于从上到下再dp一次
if(p==-1)up[u]=1;L[0]=1;
int num=0;
for(int i=head[u],j=0;i!=-1;i=e[i].next,j++){
int v=e[i].to;
temp[num++]=v;
if(p==v){
L[j+1]=L[j];
continue;
}
L[j+1]=L[j]*(dp[v]+1)%mod;
}
R[num-1]=up[u];
for(int i=num-1;i>0;i--){
if(temp[i]==p){
R[i-1]=R[i];
continue;
}
R[i-1]=R[i]*(dp[temp[i]]+1)%mod;
}
for(int i=head[u],j=0;i!=-1;i=e[i].next,j++){
int v=e[i].to;
if(v==p)continue;
up[v]=(L[j]*R[j]%mod+1)%mod;
}
for(int i=head[u];i!=-1;i=e[i].next){
int v=e[i].to;
if(v==p)continue;
DFS(v,u);
}
}
void input(){
in = new FastScanner(System.in);
e=new edge[2*N];
head=new int[N];
dp=new long[N];
L=new long[N];
R=new long[N];
ans=new long[N];
up=new long[N];
Arrays.fill(head, -1);
int n=in.nextInt();
cnt=0;
for(int i=2;i<=n;i++){
int v=in.nextInt();
addedge(i,v);
addedge(v,i);
}
DP(1,-1);
DFS(1,-1);
for(int i=1;i<=n;i++)
System.out.print(up[i]*dp[i]%mod+" ");
}
public static void main(String[] args){
new cf().input();
}
}
class edge{
int from,to,next;
}
class FastScanner {
BufferedReader br;
StringTokenizer st;
public FastScanner(File f) {
try {
br = new BufferedReader(new FileReader(f));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
public FastScanner(InputStream f) {
br = new BufferedReader(new InputStreamReader(f));
}
String next() {
while (st == null || !st.hasMoreTokens()) {
String s = null;
try {
s = br.readLine();
} catch (IOException e) {
e.printStackTrace();
}
if (s == null)
return null;
st = new StringTokenizer(s);
}
return st.nextToken();
}
boolean hasMoreTokens() {
while (st == null || !st.hasMoreTokens()) {
String s = null;
try {
s = br.readLine();
} catch (IOException e) {
e.printStackTrace();
}
if (s == null)
return false;
st = new StringTokenizer(s);
}
return true;
}
int nextInt() {
return Integer.parseInt(next());
}
long nextLong() {
return Long.parseLong(next());
}
double nextDouble() {
return Double.parseDouble(next());
}
String nextLine() {
String str = "";
try {
str = br.readLine();
} catch (IOException e) {
e.printStackTrace();
}
return str;
}
}
CodeForces 543d Road Improvement(巧妙地树形dp)
最新推荐文章于 2021-07-15 08:15:48 发布
博客探讨了如何使用树形动态规划解决CodeForces上的543d Road Improvement问题。通过将树划分为两部分并从上到下递归计算,实现了巧妙的dp值计算。文章详细介绍了如何计算以任意节点为根的子树dp值,并提供了完整的Java代码实现。
摘要由CSDN通过智能技术生成