CodeForces 543d Road Improvement(巧妙地树形dp)
2015-08-03 21:26
429 查看
//如何求树上任意一点为根的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 ; 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 ; dp=new long ; L=new long ; R=new long ; ans=new long ; up=new long ; 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; } }
相关文章推荐
- 树形DP 或 最小顶点覆盖=最大匹配(双向图)(HDU 1053)
- [BZOJ1017][JSOI2008][树形DP]魔兽地图DotR
- ZOJ3824 Fiber-optic Network
- hihocoder #1035 : 自驾旅行 III 树形DP
- POJ 3342
- URAL1018
- hdu1561 zoj3201
- poj 3107 Godfather
- zoj3201Tree of Tree
- Codeforces Round #135 (Div. 2)VD. Choosing Capital for Treeland
- POJ 1848 Tree
- 树形dp简单总结
- Party at Hali-Bula
- zoj cut the tree(树形dp,小细节真的很多)
- poj 2486 Apple Tree(树形dp)
- poj 1155 TELE(树形泛化背包dp)
- 树形DP
- HDU 1520 Anniversary party (树形dp) 解题报告
- POJ 1463 Strategic game (树形DP) 解题报告
- hdu 1561 树形dp+背包+dfs