[BZOJ 3270] 博物馆

[题目链接]

        https://www.lydsy.com/JudgeOnline/problem.php?id=3270

[算法]

        记fi,j表示第一个人在i , 第二个人在j的概率

        高斯消元即可

        时间复杂度 : O(N ^ 6)

[代码]

         

#include<bits/stdc++.h>
using namespace std;
const int N = 30;
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
const double eps = 1e-9;

struct edge
{
    int to , nxt;
} e[N * N * 2];

int n , m , A , B , tot;
int head[N * N];
double deg[N * N] , a[N * N][N * N] , b[N * N] , p[N * N] , ans[N * N];

template <typename T> inline void chkmin(T &x , T y) { x = min(x , y); }
template <typename T> inline void chkmax(T &x , T y) { x = max(x , y); }
template <typename T> inline void read(T &x)
{
   T f = 1; x = 0;
   char c = getchar();
   for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
   for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0';
   x *= f;
}
inline int id(int x , int y)
{
    return (x - 1) * n + y;
}
inline void addedge(int u , int v)
{
    ++tot;
    e[tot] = (edge){v , head[u]};
    head[u] = tot;
}
int dcmp(double x)
{
    if (x<=eps&&x>=-eps) return 0;
    return (x>0)?1:-1;
}

int main()
{
    
    scanf("%d%d%d%d" , &n , &m , &A , &B);
    for (int i = 1; i <= m; i++)
    {
        int u , v;
        scanf("%d%d" , &u , &v);
        addedge(u , v);
        addedge(v , u);
        deg[u] += 1.0;
        deg[v] += 1.0;
    }
    for (int i = 1; i <= n; i++) scanf("%lf" , &p[i]);
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= n; j++)
        {
            a[id(i , j)][id(i , j)] = 1;
            if (i != j) a[id(i , j)][id(i , j)] -= p[i] * p[j];
            for (int k = head[i]; k; k = e[k].nxt)
                if (e[k].to != j && e[k].to != i) a[id(i , j)][id(e[k].to , j)] -= (1 - p[e[k].to]) / deg[e[k].to] * p[j];
            for (int k = head[j]; k; k = e[k].nxt)
                if (i != e[k].to && j != e[k].to) a[id(i , j)][id(i , e[k].to)] -= (1 - p[e[k].to]) / deg[e[k].to] * p[i];
            for (int k = head[i]; k; k = e[k].nxt)
            {
                for (int l = head[j]; l; l = e[l].nxt)
                {
                    if (e[k].to != e[l].to)
                        a[id(i , j)][id(e[k].to , e[l].to)] -= (1 - p[e[k].to]) / deg[e[k].to] * (1 - p[e[l].to]) / deg[e[l].to];
                }
            }
        }
    }
    b[id(A , B)] = 1.0;
    for (int i=1;i<=n*n;++i)
    {
        int num=i;
        for (int j=i+1;j<=n*n;++j)
            if (dcmp(a[j][i]-a[num][i])>0) num=j;
        if (num!=i)
        {
            for (int j=1;j<=n*n;++j) swap(a[num][j],a[i][j]);
            swap(b[num],b[i]);
        }
        for (int j=i+1;j<=n*n;++j)
            if (dcmp(a[j][i]))
            {
                double t=a[j][i]/a[i][i];
                for (int k=1;k<=n*n;++k)
                    a[j][k]-=t*a[i][k];
                b[j]-=b[i]*t;
            }
    }
    for (int i=n*n;i>=1;--i)
    {
        for (int j=i+1;j<=n*n;++j) b[i]-=a[i][j]*ans[j];
        ans[i]=b[i]/a[i][i];
    }
    for (int i = 1; i <= n; i++) printf("%.6lf " , ans[id(i , i)]);
    printf("\n");
    
    return 0;
}

 

posted @ 2019-02-13 22:56  evenbao  阅读(224)  评论(0编辑  收藏  举报