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]);
 }
posted @ 2022-01-27 17:10  kid_magic  阅读(177)  评论(2编辑  收藏  举报