Problem Description
Young theoretical computer scientist Fxx has a tree.
You are given a rooted tree with n vertices,numbered from 1 to n(vertex 1 is the root).Each vertex of the tree has a value Ai and a color,which is either black or white.
Now consider a reverse operation: Choose a vertex X randomly.When X is chosen,its color changes.Meanwhile,the color of a vertex K changes as well if and only if X is an ancestor of K and the distance between them is no more than AX .
Fxx need to find out the expected number of operations to turn the whole tree black.Can you help him?
You are given a rooted tree with n vertices,numbered from 1 to n(vertex 1 is the root).Each vertex of the tree has a value Ai and a color,which is either black or white.
Now consider a reverse operation: Choose a vertex X randomly.When X is chosen,its color changes.Meanwhile,the color of a vertex K changes as well if and only if X is an ancestor of K and the distance between them is no more than AX .
Fxx need to find out the expected number of operations to turn the whole tree black.Can you help him?
Input
In the first line, there is an integer
T(T≤100)
indicating the number of test cases.
For each test case,the first line contains one integers n(1\leq n\leq 50), indicating the number of vertice.
In the next n-1 lines, Each line contains two integers u and v meaning that vertice u is the father of vertice v .
In the next line contains n integers A1,A2,…,An(0≤Ax≤n) .
In the next line contains n integers C1,C2,…,Cn , indicating the color of each vertice( Cx=0 means the color of vertice x is white, Cx=1 means the color of vertice x is black)
For each test case,the first line contains one integers n(1\leq n\leq 50), indicating the number of vertice.
In the next n-1 lines, Each line contains two integers u and v meaning that vertice u is the father of vertice v .
In the next line contains n integers A1,A2,…,An(0≤Ax≤n) .
In the next line contains n integers C1,C2,…,Cn , indicating the color of each vertice( Cx=0 means the color of vertice x is white, Cx=1 means the color of vertice x is black)
Output
For each test case, output the answer.
Each answer is rounded to three decimal places.
For example,if the answer is "<b>3.7998</b>", you should output “3.800”.
Each answer is rounded to three decimal places.
For example,if the answer is "<b>3.7998</b>", you should output “3.800”.
Sample Input
1 2 1 2 0 0 1 0
Sample Output
3.000
Source
给你一棵树,点有黑白两色。每次随机选一个点,把他和他子树中距离<=ai的点颜色翻转
问期望把整棵树变黑的操作次数
这题的出题人绝对不适合出题
首先a和c在测试数据中是反的
然后这题这么高的精度不给个SPJ,导致写法不同基本过不去
我随机他的范围有的数据要输出多达18位有效数字
讲下做法吧
这题很明显是高斯消元的题目
首先我们发现,对于一个点,所有能影响到他的父亲状态如果确定,那么他的操作状态也就确定了
f[i]表示有i个点状态和最终状态【黑】不同,到期望状态的操作数
那么有转移式f[i]=f[i+1]*(n-i)/n+f[i-1]*i/n+1;
然后我们可以列出方程组,解出来即可
有x个点状态不同那么答案就是f[x]
贴个过不去的代码吧。对拍的时候精度被卡掉了
#include<cstdio>
#include<string>
#include<iomanip>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
struct line
{
int s,t;
int next;
}a[101];
int head[51];
int edge;
inline void add(int s,int t)
{
a[edge].next=head[s];
head[s]=edge;
a[edge].s=s;
a[edge].t=t;
}
long double eps=1e-12;
bool l[511];
long double ans[511];
long double ax[511][511];
int n;
inline int solve()
{
int res=0,r=1;
int i,j,k;
for(i=1;i<=n;i++)
l[i]=false;
for(i=1;i<=n;i++)
{
for(j=r;j<=n;j++)
{
if(fabs(ax[j][i])>eps)
{
for(k=i;k<=n+1;k++)
swap(ax[j][k],ax[r][k]);
break;
}
}
if(fabs(ax[r][i])<eps)
{
res++;
continue;
}
for(j=1;j<=n;j++)
{
if(j!=r&&fabs(ax[j][i])>eps)
{
long double tmp=ax[j][i]/ax[r][i];
for(k=i;k<=n+1;k++)
ax[j][k]-=tmp*ax[r][k];
}
}
/* for(int i=1;i<=n;i++)
{
for(int j=1;j<=n+1;j++)
printf("%.3f ",ax[i][j]);
printf("\n");
}
printf("\n");*/
l[i]=true;
r++;
}
for(i=1;i<=n;i++)
{
if(l[i])
{
for(j=1;j<=n;j++)
{
if(fabs(ax[j][i])>eps)
ans[i]=ax[j][n+1]/ax[j][i];
}
}
}
return res;
}
int x1[51],x2[51],fa[51];
int edg[51];
bool fx[51],v[51];
inline void findx(int d,int dep,int lim)
{
if(dep>lim)
return ;
if(dep!=0)
v[d]=(!v[d]);
int i;
for(i=head[d];i!=0;i=a[i].next)
{
int t=a[i].t;
findx(t,dep+1,lim);
}
}
inline void dfs(int d)
{
int i,s=1,t=fa[d],sum=0;
if(v[d])
fx[d]=(x2[d]==1);
else
fx[d]=(x2[d]!=1);
if(fx[d])
findx(d,0,x1[d]);
for(i=head[d];i!=0;i=a[i].next)
{
t=a[i].t;
dfs(t);
}
}
int main()
{
freopen("test.in","r",stdin);
freopen("test.out","w",stdout);
int T;
scanf("%d",&T);
while(T>0)
{
T--;
scanf("%d",&n);
memset(head,0,sizeof(head));
memset(edg,0,sizeof(edg));
edge=0;
int i,s,t;
for(i=1;i<=n-1;i++)
{
scanf("%d%d",&s,&t);
edge++;
add(s,t);
edg[t]++;
fa[t]=s;
}
for(i=1;i<=n;i++)
scanf("%d",&x2[i]);
for(i=1;i<=n;i++)
scanf("%d",&x1[i]);
memset(ax,0,sizeof(ax));
long double nn=(long double)n;
/*ax[1][1]=nn;
ax[1][2]=-(long double)(n-1);
ax[1][n+1]=nn;*/
ax[1][1]=1;
ax[1][2]=-(long double)(n-1)/nn;
ax[1][n+1]=1;
for(i=2;i<=n;i++)
{
/*ax[i][i-1]=-(long double)i;
ax[i][i]=nn;
ax[i][i+1]=-(long double)(nn-i);
ax[i][n+1]=nn;*/
ax[i][i-1]=-(long double)i/nn;
ax[i][i]=1;
ax[i][i+1]=-(long double)(nn-i)/nn;
ax[i][n+1]=1;
}
/* for(i=1;i<=n;i++)
{
for(int j=1;j<=n+1;j++)
printf("%.3f ",ax[i][j]);
printf("\n");
}
printf("\n");*/
memset(v,false,sizeof(v));
solve();
int rt=0;
for(i=1;i<=n;i++)
if(edg[i]==0)
rt=i;
fa[rt]=0;
memset(fx,false,sizeof(fx));
dfs(rt);
int sum=0;
for(i=1;i<=n;i++)
if(fx[i])
sum++;
printf("%.3f\n",double(ans[sum]));
// cout<<fixed<<setprecision(3)<<ans[sum]<<endl;
}
return 0;
}