P2973 [USACO10HOL]Driving Out the Piggies G(高斯消元求期望)

https://www.luogu.com.cn/problem/P2973

题目描述:一个无向图,节点1有一个炸弹,在每个单位时间内,有p/q的概率在这个节点炸掉,有1-p/q的概率随机选择一条出去的路到其他的节点上。问最终炸弹在每个节点上爆炸的概率。

搬运洛谷的题解:https://siyuan.blog.luogu.org/solution-p2973

 

在dp顺序混乱的时候,就可以开始考虑转换成方程组再高斯消元。

正如上面的式子,把右边Σ的式子移到左边,就得到一个n元一次方程。

其次考虑增广列b[1~n]应该是什么。

移项后很明显b[1]=1,b[其他]=0。

代码:

#include<cstdio>
// #include<iostream>
// #include<deque>
// #include<cstring>
// #include<cmath>
// #include<map>
// #include<vector>
// #include<stack>
// #include<algorithm>
// #include<queue>
// #include<set>
#include<bits/stdc++.h>
#define sd(x) scanf("%d",&x)
#define lsd(x) scanf("%lld",&x)
#define sf(x) scanf("%lf",&x)
#define ms(x,y) memset(x,y,sizeof x)
#define fu(i,a,b) for(register int i=a;i<=b;i++)
#define fd(i,a,b) for(register int i=a;i>=b;i--)
#define all(a) a.begin(),a.end()
#define range(a,x,y) a+x,a+y+x
#define dbug printf("bbbk\n")
#define R register
using namespace std;
using namespace __gnu_cxx;
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef pair<ll,ll> P;
const int N=300+99;
const int MN=1e7+9;
const ll mod=1e9+7;
const int MAX=1e9;
const ll INF=1e9+7;
int n,m,d[N],to[N][N];
bitset<N> p[N];
double eps=1e-10;
double a[N][N];
inline void guass()
{
    int now=1;
    fu(i,1,n)
    {
        int p=now;
        fu(j,now+1,n)
        {
            if(fabs(a[j][i])>fabs(a[p][i])) p=j;
        }
        if(fabs(a[p][i])<=eps) continue;
        swap(a[now],a[p]);
        fu(j,1,n)
        {
            if(j==now) continue;
            if(fabs(a[j][i])<=eps) continue;
            double r=a[j][i]/a[now][i];
            fu(k,i,n+1) a[j][k]-=a[now][k]*r;
        }
        now++;
    }
}
int main()
{
    cin>>n>>m;
    double p,q;cin>>p>>q;
    fu(i,1,m)
    {
        int u,v;cin>>u>>v;
        to[u][v]=to[v][u]=1;
        d[v]++,d[u]++;
    }
    fu(i,1,n)
    {
        a[i][i]=1;
        fu(j,1,n)
        {
            if(i!=j&&to[i][j]) a[i][j]-=(1.0-p/q)/d[j];//i为爆炸点
        }
    }
    a[1][n+1]=1;//增广列b[1]=1,其余b[i]=0。
    guass();
    fu(i,1,n) printf("%.9f\n",a[i][n+1]/a[i][i]*(p/q));
    return 0;
}

 

posted on 2021-04-26 14:11  Aminers  阅读(77)  评论(0编辑  收藏  举报

导航