http://poj.org/problem?id=2057
题意比较简单
是典型的树 DP
思路:
先建树 然后一遍DFS求的每个节点的 访问一遍失败回来的总步数 和每个子树的叶子节点树
再对每个节点后面的子节点按照优先级排序 就是确定先访问谁
代码及其注释:
#include<iostream> #include<stdio.h> #include<string.h> #include<queue> #include<cmath> #include<stack> #include<algorithm> #define LL long long using namespace std; const int N=1005; struct node { int sum; struct tt *next; }mem[N]; struct tt { int j; struct tt *next; }; struct link { char c; int pre;//父节点 int leafnum;//叶子节点数 int backnum;//失败返回的步数 }point[N]; void build(int i,int j) { struct tt *t=new tt; t->j=j; t->next=mem[i].next; mem[i].next=t; } void Dele(int n) { struct tt *t; for(int i=1;i<=n;++i) { while(mem[i].next!=NULL) { t=mem[i].next; mem[i].next=t->next; delete t; } } } void mysort(int x)//按优先级排序 { if(mem[x].next==NULL) return ; struct tt *t,*w; for(t=mem[x].next;t!=NULL;t=t->next) { for(w=t->next;w!=NULL;w=w->next) { if(point[t->j].leafnum*(point[w->j].backnum+2)<(point[t->j].backnum+2)*point[w->j].leafnum) { swap(t->j,w->j); } } } } void Dfs1(int x)//求叶子节点数 和失败返回步数 { struct tt *t; t=mem[x].next; point[x].leafnum=0; point[x].backnum=0; while(t!=NULL) { Dfs1(t->j); point[x].leafnum+=point[t->j].leafnum; point[x].backnum+=(2+point[t->j].backnum); t=t->next; } if(mem[x].next==NULL) { point[x].leafnum=1; } if(point[x].c=='Y') { point[x].backnum=0; } } void Dfssum(int x)//统计总和 { if(mem[x].next==NULL) { mem[x].sum=0;return; } mem[x].sum=0; struct tt *t; t=mem[x].next; int itemp=0; while(t!=NULL) { Dfssum(t->j); mem[x].sum+=(itemp*point[t->j].leafnum+mem[t->j].sum); itemp+=(point[t->j].backnum+2); t=t->next; } mem[x].sum+=point[x].leafnum; } int main() { int n; while(scanf("%d",&n)!=EOF,n) { for(int i=1;i<=n;++i) { scanf("%d %c",&point[i].pre,&point[i].c); if(point[i].pre==-1) continue; build(point[i].pre,i);//建树 } Dfs1(1); for(int i=1;i<=n;++i) mysort(i);//排序 Dfssum(1); printf("%.4f\n",(1.0*mem[1].sum/point[1].leafnum)); Dele(n); } }