1. 程式人生 > >[Luogu P2973&BZOJ 1778][USACO10HOL]趕小豬DOtP(高斯消元+期望)

[Luogu P2973&BZOJ 1778][USACO10HOL]趕小豬DOtP(高斯消元+期望)

http ios iostream 爆炸 head swa sca 選擇 main

Description

一個無向圖,節點1有一個炸彈,在每個單位時間內,有可能在這個節點炸掉,也有p/q的概率隨機選擇一條出去的路到其他的節點上。問最終炸彈在每個節點上爆炸的概率。

Solution

沒錯它就是BZOJ 1778…在bzoj上是權限題

炸彈最終爆炸的概率是1(可能是在無窮無盡的時間之後…),於是到達某一點的概率除以到達所有點的概率就是在這個節點上爆炸的概率

f[u]=∑f[v]*(1-p/q)/d[v]

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include
<cstring> using namespace std; int n,m,d[303],head[303],cnt=0; double a[303][303],f[303],p,q; struct Node { int next,to; }Edges[100005]; void addedge(int u,int v) { Edges[++cnt].next=head[u]; head[u]=cnt; Edges[cnt].to=v; } void Gauss() { for(int i=1;i<=n;i++) {
int maxline=i; for(int j=i;j<=n;j++) if(a[j][i]>a[maxline][i])maxline=j; if(maxline!=i) for(int j=i;j<=n+1;j++) swap(a[maxline][j],a[i][j]); for(int j=i+1;j<=n;j++) { double t=a[j][i]/a[i][i]; for(int
k=i;k<=n+1;k++) a[j][k]-=t*a[i][k]; } } for(int i=n;i>0;i--) { for(int j=n;j>i;j--) a[i][n+1]-=f[j]*a[i][j]; f[i]=a[i][n+1]/a[i][i]; } } int main() { memset(head,-1,sizeof(head)); scanf("%d%d%lf%lf",&n,&m,&p,&q); for(int i=1;i<=m;i++) { int u,v; scanf("%d%d",&u,&v); addedge(u,v); addedge(v,u); d[u]++,d[v]++; } for(int i=1;i<=n;i++) { a[i][i]+=1; for(int j=head[i];~j;j=Edges[j].next) { int v=Edges[j].to; a[v][i]-=(1-p/q)/d[i]; } } a[1][n+1]+=1-p/q; Gauss(); double sum=0; for(int i=1;i<=n;i++)sum+=f[i]; for(int i=1;i<=n;i++) printf("%.9lf\n",f[i]/sum); return 0; }

[Luogu P2973&BZOJ 1778][USACO10HOL]趕小豬DOtP(高斯消元+期望)