problem:
给n个点,m条边的一个连通图,每两个点之间最多一条边,起始时x,y两个人在A,B两点,求他们在每个点相遇的概率。
n<=20
solution:
(还是逆序定义..)
定义f[i][j]为x,y分别走到i,j的期望步数
f[i][j]=∑f[q][w]* (p[q]or(1-p[q])*1/degree[q]) * (p[w]or(1-p[w])*1/degree[w]) (q为与i相连的边 w为与j相连的边 i,j包括在q,w之内 但是q,w不能相等)
特别的 f[A][B]=∑f[q][w]* (p[q]or(1-p[q])*1/degree[q]) * (p[w]or(1-p[w])*1/degree[w]) + 1
这样得到n^2个方程,高斯消元解得f[i][i](i<=n) 的期望步数,之后可以求出概率
(ps:我因为打错了高斯板子调了很长时间.............)
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<cmath> 5 #define mem(a,b) memset(a,b,sizeof(a)) 6 #define dd double 7 using namespace std; 8 void swap(dd &x,dd &y){dd temp=x;x=y;y=temp;} 9 dd abss(dd x){return x<0?-x:x;} 10 struct son 11 { 12 int v,next; 13 }; 14 son a1[501]; 15 int first[501],e; 16 void addbian(int u,int v) 17 { 18 a1[e].v=v; 19 a1[e].next=first[u]; 20 first[u]=e++; 21 } 22 23 int n,m,A,B; 24 dd p[501],deg[501]; 25 int u,o; 26 dd a[501][501],b[501],ans[501]; 27 int ji[501][501],limit[501]; 28 int num; 29 30 void gaos() 31 { 32 int now=1; 33 for(int k=1;k<=num;++k,++now) 34 { 35 int order=now; 36 for(int i=now+1;i<=num;++i) 37 if(abss(a[i][k])>abss(a[order][k])) 38 order=i; 39 if(order!=now) 40 { 41 for(int j=1;j<=num;++j) 42 swap(a[now][j],a[order][j]); 43 swap(b[now],b[order]); 44 } 45 if(!a[now][k]) 46 { 47 --now; 48 continue; 49 } 50 for(int i=now+1;i<=num;++i) 51 { 52 dd temp=a[i][k]/a[now][k]; 53 for(int j=k;j<=num;++j) 54 a[i][j]-=a[now][j]*temp; 55 b[i]-=b[now]*temp; 56 } 57 } 58 59 for(int i=num;i>=1;--i) 60 { 61 for(int j=num;j>i;--j) 62 b[i]-=a[i][j]*ans[j]; 63 ans[i]=b[i]/a[i][i]; 64 } 65 } 66 67 int main(){ 68 mem(first,-1); 69 scanf("%d%d%d%d",&n,&m,&A,&B); 70 for(int i=1;i<=m;++i) 71 { 72 scanf("%d%d",&u,&o); 73 ++deg[u]; 74 ++deg[o]; 75 addbian(u,o); 76 addbian(o,u); 77 } 78 79 for(int i=1;i<=n;++i) 80 addbian(i,i); 81 82 for(int i=1;i<=n;++i) 83 scanf("%lf",&p[i]); 84 85 for(int i=1;i<=n;++i) 86 for(int j=1;j<=n;++j) 87 ji[i][j]=(i-1)*n+j; 88 89 b[ji[A][B]]=-1; 90 91 for(int i=1;i<=n;++i) 92 for(int j=1;j<=n;++j) 93 { 94 a[++num][ji[i][j]]=-1; 95 for(int k=first[i];k!=-1;k=a1[k].next) 96 { 97 int tempk=a1[k].v; 98 for(int l=first[j];l!=-1;l=a1[l].next) 99 { 100 int templ=a1[l].v; 101 if(tempk==templ)continue; 102 a[num][ji[tempk][templ]]+=(tempk==i?p[tempk]:(1.0-p[tempk])*1.0/deg[tempk]) * (templ==j?p[templ]:(1.0-p[templ])*1.0/deg[templ]); 103 } 104 } 105 } 106 gaos(); 107 dd temp=0; 108 for(int i=1;i<=n;++i) 109 temp+=ans[ji[i][i]]; 110 for(int i=1;i<=n;++i) 111 printf("%.6lf ",ans[ji[i][i]]/temp); 112 //while(1); 113 return 0; 114 }