puzzle 期望樹形DP
阿新 • • 發佈:2017-10-15
之前 ace oid 輸出 etc ems 得出 algo blog
【題目描述】
【輸入格式】
【輸出格式】
【輸入樣例1】
7
1 2 1 1 4 4
【輸入樣例2】
12
1 1 2 2 4 4 3 3 1 10 8
【輸出樣例1】
1.0 4.0 5.0 3.5 4.5 5.0 5.0
【輸出樣例2】
1.0 5.0 5.5 6.5 7.5 8.0 8.0 7.0 7.5 6.5 7.5 8.0
【數據範圍】
這道題不是很難,首先我們知道每個兒子的深度是不變的,而且每個點的開始時間只和他的爸爸和他爸爸的兒子有關,於是我們就往這方面去想.
我們考慮一對父子關系,對於爸爸的每一個兒子,有1/2的幾率在當前兒子之前被走到,所以我們可以得出:
ans[now]=ans[x]+1+(size[x]-size[now]-1)/2.0;(爸爸的期望+1加上爸爸的所有兒子除了該點和他的子樹除以2)
代碼:
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #define ll long long #define il inline #define db double using namespace std; il int gi() { int x=0,y=1; char ch=getchar(); while(ch<‘0‘||ch>‘9‘) { if(ch==‘-‘) y=-1; ch=getchar(); } while(ch>=‘0‘&&ch<=‘9‘) { x=x*10+ch-‘0‘; ch=getchar(); } return x*y; } int head[1000045],cnt; struct edge { int next,to; }e[1000045]; il void add(int from,int to) { e[++cnt].next=head[from]; e[cnt].to=to; head[from]=cnt; } bool vis[100045]; int size[100045]; db ans[100045]; void dfs1(int x) { size[x]=1; int r=head[x]; while(r!=-1) { int now=e[r].to; if(!vis[now]) { vis[now]=1; dfs1(now); size[x]+=size[now]; } r=e[r].next; } } void dfs2(int x) { int r=head[x]; while(r!=-1) { int now=e[r].to; if(!vis[now]) { vis[now]=1; ans[now]=ans[x]+1+(size[x]-size[now]-1)/2.0; dfs2(now); } r=e[r].next; } } int main() { memset(head,-1,sizeof(head)); int n=gi(); int x; for(int i=2;i<=n;i++) { x=gi(); add(x,i); } vis[1]=1; dfs1(1); memset(vis,0,sizeof(vis)); vis[1]=1; ans[1]=1.0; dfs2(1); for(int i=1;i<=n;i++) printf("%.1f ",ans[i]); return 0; }
puzzle 期望樹形DP