BZOJ1778: [Usaco2010 Hol]Dotp 驱逐猪猡
给出n个节点m条边无向图,炸弹从1开始走,有p/q的概率爆炸,否则等概率移到别的点
求在每个点爆炸概率
f[i,j]-第j秒到点i的概率 W=p/q 则f[i,j]=sigma(1-W)/D[i]*f[k,j-1]
其中D[i]为点i的度,k与i有连边
Ans(i)=W(f[i,0]+f[i,1]+f[i,2]+……)
=Wf[i,0]+W(1-W)/D[i](sigma f[k,0]+sigma f[k,1]+sigma f[k,2]……)
=Wf[i,0]+sigma (1-W)/D[i]*Ans(k),高斯消元解即可。
以上为典型的错误!!系数写错,把D[i]改成D[k]即可。
第一次写,很顺;第二次,系数配错,高斯消元写错,WA两发。
很好。
1 #include<stdio.h> 2 #include<string.h> 3 #include<algorithm> 4 #include<math.h> 5 //#include<iostream> 6 using namespace std; 7 8 const double eps=1e-13; 9 int n,m; 10 #define maxn 311 11 #define maxm 100011 12 struct Edge{int to,next;}; 13 struct Graph 14 { 15 Edge edge[maxm]; 16 int first[maxn],le,du[maxn]; 17 Graph() 18 { 19 memset(first,0,sizeof(first));le=2; 20 memset(du,0,sizeof(du)); 21 } 22 void in(int x,int y) 23 { 24 edge[le].to=y; 25 edge[le].next=first[x]; 26 first[x]=le++; 27 } 28 void insert(int x,int y) 29 { 30 in(x,y); 31 in(y,x); 32 du[x]++;du[y]++; 33 } 34 }g; 35 double mat[maxn][maxn]; 36 int x,y;double w; 37 void gauss() 38 { 39 for (int i=1;i<=n;i++) 40 { 41 int r=i; 42 for (int j=i+1;j<=n;j++) if (mat[j][i]>mat[r][i]) r=j; 43 for (int j=i;j<=n+1;j++) {double t=mat[r][j];mat[r][j]=mat[i][j];mat[i][j]=t;} 44 for (int j=i+1;j<=n;j++) 45 for (int k=n+1;k>=i;k--) 46 mat[j][k]-=mat[j][i]/mat[i][i]*mat[i][k]; 47 } 48 for (int i=n;i>=1;i--) 49 { 50 for (int j=n;j>i;j--) mat[i][n+1]-=mat[j][n+1]*mat[i][j]; 51 mat[i][n+1]/=mat[i][i]; 52 } 53 } 54 int main() 55 { 56 scanf("%d%d%d%d",&n,&m,&x,&y); 57 if (x>y) x=y;w=(double)x/y; 58 for (int i=1;i<=m;i++) 59 { 60 scanf("%d%d",&x,&y); 61 g.insert(x,y); 62 } 63 for (int i=1;i<=n;i++) 64 { 65 for (int j=1;j<=n+1;j++) mat[i][j]=0.0; 66 for (int j=g.first[i];j;j=g.edge[j].next) 67 { 68 Edge &e=g.edge[j]; 69 mat[i][e.to]+=(w-1)/g.du[e.to]; 70 } 71 mat[i][i]=1.0; 72 } 73 mat[1][n+1]=w; 74 gauss(); 75 for (int i=1;i<=n;i++) printf("%.9f\n",mat[i][n+1]); 76 return 0; 77 }