记录编号 87235 评测结果 AAAAAAAAAA
题目名称 289.[NOI 2008]奥运物流 最终得分 100
用户昵称 cstdio 是否通过 通过
代码语言 C++ 运行时间 0.495 s
提交时间 2014-02-02 22:48:12 内存使用 5.55 MiB
显示代码纯文本
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<cmath>
using namespace std;
const int SIZEN=70;
int N,M;
double K;
int father[SIZEN]={0};
vector<int> son[SIZEN];
double C[SIZEN]={0};
double f[SIZEN][SIZEN][SIZEN]={0};
double g[SIZEN][SIZEN][SIZEN]={0};
int X;//当前接到1上的环上的点
void DP(int u,int maxd){//对结点u,计算所有离根不超过maxd的f值
	//cout<<u<<" "<<maxd<<endl;
	for(int i=0;i<son[u].size();i++) if(son[u][i]!=X&&son[u][i]!=1) DP(son[u][i],maxd+1);
	//cout<<u<<" "<<maxd<<"as follow:"<<endl;
	for(int d=1;d<=maxd;d++){
		int nowchange;
		if(maxd>1&&d==1) nowchange=1;//耗费了一次修改机会来把当前点挂在根上
		else nowchange=0;
		double F[SIZEN]={0};
		for(int i=0;i<son[u].size();i++){
			int v=son[u][i];
			if(v==X||v==1) continue;
			//cout<<u<<" "<<maxd<<" "<<v<<"as follow:"<<endl;
			for(int j=M;j>=0;j--){//一个v只能更新一次,诸如"v改两次"和"v改三次"不能作为一个物品
				//for(int k=0;k<=M;k++){cout<<F[k]<<" ";}cout<<endl;
				for(int k=j;k>=0;k--){
					//cout<<v<<" "<<j-k<<" "<<d<<" "<<F[k]<<" "<<g[v][j-k][d]<<endl;
					//cout<<k<<" "<<j<<" "<<F[k]<<endl;
					F[j]=max(F[j],F[k]+g[v][j-k][d]);
					//cout<<j<<" "<<F[0]<<" "<<F[1]<<endl;
				}
				//for(int k=0;k<=M;k++){cout<<F[k]<<" ";}cout<<endl;cout<<endl;
			}
			/*for(int j=M;j>=0;j--){
				//for(int k=0;k<=M;k++){cout<<F[k]<<" ";}cout<<endl;
				for(int k=M;k>=j;k--){
					//cout<<v<<" "<<j<<" "<<d<<" "<<F[k-j]<<" "<<g[v][j][d]<<endl;
					//cout<<k-j<<" "<<F[k-j]<<endl;
					F[k]=max(F[k],F[k-j]+g[v][j][d]);
				}
				//for(int k=0;k<=M;k++){cout<<F[k]<<" ";}cout<<endl;cout<<endl;
			}*/
		}
		for(int i=nowchange;i<=M;i++){
			//cout<<u<<" "<<i<<" "<<d<<" "<<F[i-nowchange]<<" "<<C[u]*pow(K,d+0.0)<<endl;
			f[u][i][d]=F[i-nowchange]+C[u]*pow(K,d+0.0);
			//cout<<d<<" "<<pow(K,d+0.0)<<endl;
		}
		//for(int i=0;i<=M;i++) g[u][i][d]=max(f[u][i][d],f[u][i][1]);
		//for(int i=0;i<=M;i++) cout<<F[i]<<" ";cout<<endl;
	}
	for(int j=0;j<=M;j++){
		for(int d=0;d<maxd;d++){
			//cout<<u<<" "<<j<<" "<<d<<" "<<f[u][j][d+1]<<" "<<f[u][j][1]<<endl;
			g[u][j][d]=max(f[u][j][d+1],f[u][j][1]);
		}
	}
	//for(int i=0;i<=M;i++){for(int j=0;j<maxd;j++){cout<<g[u][i][j]<<" ";}cout<<endl;}
}
void work(void){
	int len=2;
	double ans=0;
	for(X=father[1];X!=1;X=father[X],len++){
		memset(f,0,sizeof(f));
		memset(g,0,sizeof(g));
		for(int i=2;i<=N;i++) if(father[i]==1||i==X) DP(i,1);
		double F[SIZEN]={0};
		for(int i=2;i<=N;i++){
			if(!(father[i]==1||i==X)) continue;
			for(int j=M;j>=0;j--){
				for(int k=j;k>=0;k--){
					F[j]=max(F[j],F[k]+f[i][j-k][1]);
				}
			}
			/*for(int j=0;j<=M;j++){
				for(int k=M;k>=j;k--) F[k]=max(F[k],F[k-j]+f[i][j][1]);
			}*/
		}
		int leftchange;
		if(father[X]==1) leftchange=M;
		else leftchange=M-1;
		for(int i=0;i<=leftchange;i++) ans=max(ans,(F[i]+C[1])/(1-pow(K,len+0.0)));
	}
	printf("%.2lf",ans);
}
void read(void){
	scanf("%d%d%lf",&N,&M,&K);
	for(int i=1;i<=N;i++){
		scanf("%d",&father[i]);
		son[father[i]].push_back(i);
	}
	for(int i=1;i<=N;i++) scanf("%lf",&C[i]);
}
int main(){
	freopen("trans.in","r",stdin);
	freopen("trans.out","w",stdout);
	read();
	work();
	return 0;
}