CodeForces 543d Road Improvement(巧妙地樹形dp)

//如何求樹上任意一點爲根的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;
	}
}

發佈了124 篇原創文章 · 獲贊 46 · 訪問量 15萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章