Maze
考虑每一个迷宫,其实问题可以转化为\(n\)的游走,从1号点开始到停止的路点权和
考虑一个迷宫从1号点走出来的期望步数,设\(dp[i]\)表示迷宫中的\(i\)号点走到n+1号点的期望步数
\(dp[i]=dp[1]*k_i+(1-p_i-k_i)*(\dfrac{dp[fa]+\sum dp[son]}{d_i}),d为i的度数\)
直接高斯消元会T
对于树的叶子节点,\(dp[leaf]=dp[1]*k_{leaf}+(1-p_{leaf}-k_{leaf})*(\dfrac{dp[fa]}{d_{leaf}})\)
实际上,叶子只与1与他的父亲有关
而叶子的上面i,他的dp值与\(1,fa[i],son[i]\),有关,而\(son[i]只与i,1有关\)
所以,i的值可以只与\(1,fa\)有关
递归处理,设\(dp[i]=A[i]dp[fa]+B[i]dp[1]+C[i]\)
\(dp[i]=dp[1]k_i+(1-p_i-k_i)*(\dfrac{dp[fa]+\sum {dp[i]A[son]+B[son]dp[1]+C[son]}}{d_i})\)
\(dp[1](1-\dfrac{\sum{A[son]}*(1-p_i-k_i)}{d})=dp[1](k_i+\dfrac{\sum{B[son]}*(1-p_i-k_i)}{d})+dp[fa]*\dfrac{(1-p_i-k_i)}{d}+(1-p_i-k_i)+\dfrac{\sum{C[son]}*(1-p_i-k_i)}{d}=dp[fa]A[i]+dp[1]B[i]+C[i]\)
\(由此解出A[i],B[i],C[i]\)
\(这样可以线性求出dp[1],设第i个迷宫的dp[1]为a[i]\)
回到之前的N个迷宫,设dp[i]为该点出发的期望步数
\(dp[i]=\sum\dfrac{dp[v]}{d+1}+a[i]\)
\(高斯消元即可\)
#include<bits/stdc++.h>
#define eps 1e-9
using namespace std;
const int MAXN=1e4+5;
void read(int &x) {
x = 0;
int f = 1;
char s = getchar();
while (s > '9' || s < '0') {
if (s == '-') f = -1;
s = getchar();
}
while (s >= '0' && s <= '9') {
x = (x << 3) + (x << 1) + (s - '0');
s = getchar();
}
x *= f;
}
struct Martix{
double val[555][555];
int n,m;
void clear()
{
memset(val,0,sizeof(val));
}
void print()
{
for(int i=0;i<n;i++)
{
for(int j=0;j<=m;j++)
{
printf("%lf ",val[i][j]);
}
printf("\n");
}
}
int guess()
{
int r=0;
int c=0;
for(;r<n&&c<n;r++,c++)
{
int Main_element=r;
int maxi_=val[r][c];
for(int i=r+1;i<n;i++)
{
if(fabs(val[i][c])>fabs(val[Main_element][c]))
{
Main_element=i;
}
}
if(fabs(val[Main_element][c])<eps)
{
r--;
continue;
}
if(r!=Main_element)
{
for(int i=c;i<=m;i++)
{
swap(val[Main_element][i],val[r][i]);
}
}
for(int i=0;i<n;i++)
{
if(i==r)
{
continue;
}
double detl=(val[i][c])/(val[r][c]);
for(int j=c;j<=m;j++)
{
val[i][j]-=val[r][j]*detl;
}
}
}
return 1;
}
}A;
int m;
int n;
vector<int>g[MAXN];
int d[MAXN];
double k[MAXN];
double p[MAXN];
int x,y;
double Aw[MAXN];
double B[MAXN];
double C[MAXN];
void dfs(int x,int f)
{
double suma=0;
double sumb=0;
double sumc=0;
for(int i=0;i<g[x].size();i++)
{
int v=g[x][i];
if(v==f)
{
continue;
}
dfs(v,x);
suma+=Aw[v];
sumb+=B[v];
sumc+=C[v];
}
double sf=p[x]*1.0/d[x];
//printf("%dsagdsgA\n",d[x]);
double df=(1-sf*suma);
if(df<eps)
{
printf("PF\n");
exit(0);
}
Aw[x]=sf/df;
B[x]=(k[x]+sf*sumb)/df;
C[x]=(p[x]+sf*sumc)/df;
return;
}
double ned[555];
int nt;
double dp[15][10005];
int main()
{
freopen("maze.in","r",stdin);
freopen("maze.out","w",stdout);
scanf("%d",&nt);
scanf("%d",&m);
for(int fot=1;fot<=nt;fot++)
{
// printf("%d老fhdz比hz芳d大sgdxh师tahg和jhg9=\89px小tfgbjglnbkv小\n",fot);
read(n);
for(int i=1;i<=n;i++)
{
g[i].clear();
}
for(int i=1;i<n;i++)
{
read(x,y);
g[x].push_back(y);
g[y].push_back(x);
}
for(int i=1;i<=n;i++)
{
Aw[i]=0;
B[i]=0;
C[i]=0;
d[i]=g[i].size();
read(x);
read(y);
k[i]=(x*1.0/100);
p[i]=((100-x-y)*1.0/100);
}
dfs(1,1);
if((1-B[1])<eps)
{
printf("PF");
return 0;
}
ned[fot]=(C[1])/(1-B[1]);
// printf("从小都是根据SFdsgAS%lf %lf %lf\n",ned[fot],C[1],1-B[1]);
}
n=nt;
for(int i=1;i<=n;i++)
{
g[i].clear();
}
for(int i=1;i<=m;i++)
{
// scanf("%d %d",&x,&y);
read(x);
read(y);
g[x].push_back(y);
}
A.n=n;
A.m=n;
for(int i=1;i<=n;i++)
{
A.val[i-1][i-1]+=1;
for(int j=0;j<g[i].size();j++)
{
int v=g[i][j];
A.val[i-1][v-1]+=-(1.0/(g[i].size()+1));
}
A.val[i-1][A.m]+=ned[i];
// printf("%lf %d %d %lf--\n",ned[i],g[i].size(),g[i].size()+1,(ned[i]*g[i].size())/(g[i].size()+1));
// printf("%lf",A.val[0][A.m]);
}
// printf("%lf",A.val[0][A.m]);
// A.print();
A.guess();
// A.print();
printf("%.3lf",A.val[0][A.m]/A.val[0][0]);
}