POJ 2057 The Lost House

vjudge

智商掉线*2...

可以看成求一种遍历叶子的顺序,使得以每个叶子为终点的路径的长度之和最小.考虑设\(f_x\)表示\(x\)子树内,以\(x\)为起点到所有叶子的路径长度之和的最小值,\(g_x\)表示从\(x\)父亲走进子树\(x\)然后遍历完一遍后出来的步数(也就是没走进终点所在子树而要浪费的步数),\(s_x\)表示\(x\)子树内叶子节点个数

先考虑\(g_x\),如果没有worm那么就是子树大小\(*2\).否则因为worm会告诉snail终点不在这个子树内,那么要遍历的联通块大小就是所有worm节点断掉儿子的边以后的联通块大小,\(g_x\)就是这个联通块大小\(*2\)

然后是\(f_x\),因为终点可能在所有儿子子树内,所以后遍历的子树的步数要加上前面遍历子树浪费的步数\(g_y\),转移要枚举遍历儿子的顺序,然后大概长这样$$f_x=(\sum_{y\in son_of_x}f_y )+(\min_{{p1,p2,p3...p_{cnt}}=son_of_x}\sum_{i=1}{cnt}s_{p_i}*(1+\sum_{j=1}g_{p_j}))$$

考虑后半部分,这个式子有点国王游戏,考虑交换两个相邻儿子的枚举顺序来优化答案,首先这不会对其他的儿子贡献产生影响,然后如果\(i\)号放\(i+1\)号儿子前面更优,相当于这种情况的和比\(i\)放后面的和要小,进一步化简可以得到要满足\(s_ig_{i+1}>s_{i+1}g_i\)这个条件,所以可以按照这个为关键字排序,然后一遍扫过去得到\(f_x\).最后输出\(\frac{f_{root}}{s_{root}}\)

#include<bits/stdc++.h>
//poj 不能用bits头,请选c++编译器
#define LL long long
#define uLL unsigned long long
#define db double

using namespace std;
const int N=1000+10;
int rd()
{
	int x=0,w=1;char ch=0;
	while(ch<'0'||ch>'9'){if(ch=='-') w=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
	return x*w;
}
int to[N<<1],nt[N<<1],hd[N],tot=1;
void add(int x,int y)
{
	++tot,to[tot]=y,nt[tot]=hd[x],hd[x]=tot;
	++tot,to[tot]=x,nt[tot]=hd[y],hd[y]=tot;
}
char cc[N];
bool v[N],bb[N];
int n,rt,sz[N],ss[N],st[N],tp;
bool cmp(int aa,int bb){return 1ll*ss[aa]*sz[bb]>1ll*ss[bb]*sz[aa];}
LL f[N];
void dp(int x,int ffa)
{
	sz[x]=1,ss[x]=f[x]=0;
	if(ffa&&!nt[hd[x]]){ss[x]=1;return;}
	for(int i=hd[x];i;i=nt[i])
	{
		int y=to[i];
		if(y==ffa) continue;
		dp(y,x),ss[x]+=ss[y];
		if(!v[x]) sz[x]+=sz[y];
	}
	tp=0;
	for(int i=hd[x];i;i=nt[i])
	{
		int y=to[i];
		if(y==ffa) continue;
		st[++tp]=y,f[x]+=f[y]+ss[y];
	}
	sort(st+1,st+tp+1,cmp);
	LL dt=0;
	for(int i=1;i<=tp;++i)
	{
		int y=st[i];
		f[x]+=ss[y]*dt;
		dt+=sz[y]*2;
	}
}

int main()
{
	int T=rd();
	while(T--)
	{
		n=rd();
		for(int i=1;i<=n;++i) hd[i]=0;
		tot=1;
		for(int i=1;i<=n;++i)
		{
			int y=rd();
			if(y>0) add(i,y);
			else rt=i;
			scanf("%s",cc);
			v[i]=cc[0]=='Y';
		}
		dp(rt,0);
		printf("%.4lf\n",f[rt]/(db)ss[rt]);
	}
	return 0;
}
posted @ 2019-08-30 16:06  ✡smy✡  阅读(117)  评论(0编辑  收藏  举报