【SDOI2014】【BZOJ3534】重建

Description

T国有N个城市,用若干双向道路连接。一对城市之间至多存在一条道路。

在一次洪水之后,一些道路受损无法通行。虽然已经有人开始调查道路的损毁情况,但直到现在几乎没有消息传回。

辛运的是,此前T国政府调查过每条道路的强度,现在他们希望只利用这些信息估计灾情。具体地,给定每条道路在洪水后仍能通行的概率,请计算仍能通行的道路恰有N-1条,且能联通所有城市的概率。

Input

输入的第一行包含整数N。

接下来N行,每行N个实数,第i+l行,列的数G[i][j]表示城市i与j之

间仍有道路联通的概率。

输入保证G[i][j]=G[j][i],且G[i][j]=0;G[i][j]至多包含两位小数。

Output

输出一个任意位数的实数表示答案。
你的答案与标准答案相对误差不超过10^(-4)即视为正确。

Sample Input

3

0 0.5 0.5

0.5 0 0.5

0.5 0.5 0

Sample Output

0.375

HINT

1 < N < =50

数据保证答案非零时,答案不小于10^-4

Source

Round 1 Day 2

看起来好像直接对输入的矩阵计算一下行列式的值就可以了…

可以个[哔——]!

根本不对!

做不出来题到处问:

哔——

最后找到了gty大哥的blog…

好详细真是感人至深QwQ

让我们来看看正确的姿势…

令矩阵里的元素P(i,j)=1?P(i,j),记一个tmp=∏(1?P(i,j))

计算新的矩阵的行列式的值再乘上这个tmp得到答案…

不明白为什么这样吧>_<

其实我也不是很明白…

我们似乎可以通过令G(i,j)=P(i,j)来得到答案。且慢!要知道这道题目对于一棵生成树来说,它的期望应该为∏(i,j)∈EP(i,j)∏(i,j)?E(1?P(i,j))。正确的方法应该为令G(i,j)=P(i,j)1?P(i,j),最后求出|det(G)|后再乘以tmp=∏(1?P(i,j)),得到的即为正确答案。

所以就是这样(终于明白一些了)

要注意1?P(i,j)有可能等于零,这时候要手动把它变成eps

以及P(i,j)和P(j,i)乘一个就行了…别乘多了…

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define MAXN 100
#define eps 1e-9
using namespace std;
int n;
double G[MAXN][MAXN];
double tmp=1;
double Gauss()
{
    double ret=1;
    for (int i=1;i<n;i++)
    {
        int now=i;
        for (int j=i+1;j<n;j++) now=fabs(G[now][i])<fabs(G[j][i])?j:now;
        if (now!=i)
            for (int j=1;j<n;j++)   swap(G[now][j],G[i][j]);
        for (int j=i+1;j<n;j++)
        {
            double temp=G[j][i]/G[i][i];
            for (int k=i;k<n;k++)   G[j][k]-=G[i][k]*temp;
        }
        if (fabs(G[i][i])<eps)  return 0;
        ret*=G[i][i];
    }
    return fabs(ret)*tmp;
}
int main()
{
    scanf("%d",&n);
    for (int i=1;i<=n;i++)
        for (int j=1;j<=n;j++)
        {
            scanf("%lf",&G[i][j]);
            double t=fabs(1-G[i][j])<eps?eps:1-G[i][j];
            if (i<j)    tmp*=t;
            G[i][j]/=t;
        }
    for (int i=1;i<=n;i++)
        for (int j=1;j<=n;j++)
            if (i!=j)   G[i][i]-=G[i][j];
    printf("%.10f\n",Gauss());
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-11-05 19:37:24

【SDOI2014】【BZOJ3534】重建的相关文章

bzoj3534 [Sdoi2014]重建

变形的$Martix-Tree$定理 发现我们要求的是$\prod_{i \in E}{p_{i}} * \prod_{i \notin E}{(1-p_{i})}$ 然后呢? 矩阵树对重边也有效对吧.考虑带权图,发现建出来的矩阵的任何一个$n-1$阶主子式的行列式的值都是其所有生成树的边权之积的和 那么就可以搞了,考虑每一条边权为$\frac{p_{i}}{(1-p_{i})}$,最后再乘一个$\prod{(1-p_{i})}$即可 1 #include<cstdio> 2 #include

[SDOI2014]重建

P3317 [SDOI2014]重建 题解 直接M-T肯定不对 推出的是对于所有树的生成概率的和,可以考虑行列式的期望,再交换求和号即可 同时乘上π(1-P)再变化初始的概率就有点厉害了 一种变化的技巧 代码: #include<bits/stdc++.h> #define il inline #define reg register int #define numb (ch^'0') #define ld long double using namespace std; typedef lo

BZOJ 3534 [Sdoi2014]重建

题解:矩阵树定理 邻接矩阵-度数矩阵(期望下) 求出来的行列式为所有(生成树边权乘积)的和 每条边边权化为 c/(1-c),最后乘上π(1-c),对1边权特殊处理一下 问题:矩阵树定理不熟,不会证明 #include<iostream> #include<cstdio> #include<cstring> #include<cmath> using namespace std; const int maxn=60; const double eps=1e-9

luogu3317 [SDOI2014]重建

原来矩阵树定理对于边是概率的情况也是适用的qwqwq. ref #include <iostream> #include <cstdio> #include <cmath> using namespace std; int n; double w[55][55], uu; const double eps=1e-7; void gauss(){ for(int i=1; i<=n; i++){ int maxi=i; for(int j=i+1; j<=n;

luoguP3317 [SDOI2014]重建 变元矩阵树定理 + 概率

首先,我们需要求的是 $$\sum\limits_{Tree} \prod\limits_{E \in Tree} E(u, v) \prod\limits_{E \notin Tree} (1 - E(u, v))$$ 我们知道变元矩阵树定理 ---> 不知道请见此 我们自然希望要求和的事物只跟生成树的边有关 因此考虑把$\prod\limits_{E \notin Tree} (1 - E(u, v))$转化为$\prod\limits_{E} (1 - E(u, v)) * \frac{1

P3317 [SDOI2014]重建

\(\color{#0066ff}{ 题目描述 }\) T国有N个城市,用若干双向道路连接.一对城市之间至多存在一条道路. 在一次洪水之后,一些道路受损无法通行.虽然已经有人开始调查道路的损毁情况,但直到现在几乎没有消息传回. 幸运的是,此前T国政府调查过每条道路的强度,现在他们希望只利用这些信息估计灾情.具体地,给定每条道路在洪水后仍能通行的概率,请计算仍能通行的道路恰有N-1条,且能联通所有城市的概率. \(\color{#0066ff}{输入格式}\) 输入的第一行包含整数N. 接下来N行

P3317 [SDOI2014]重建 变元矩阵树定理 高斯消元

传送门:https://www.luogu.org/problemnew/show/P3317 这道题的推导公式还是比较好理解的,但是由于这个矩阵是小数的,要注意高斯消元方法的使用: #include <algorithm> #include <iterator> #include <iostream> #include <cstring> #include <cstdlib> #include <iomanip> #include

bzoj 2957: 楼房重建.

2957: 楼房重建 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 2303  Solved: 1088[Submit][Status][Discuss] Description 小A的楼房外有一大片施工工地,工地上有N栋待建的楼房.每天,这片工地上的房子拆了又建.建了又拆.他经常无聊地看着窗外发呆,数自己能够看到多少栋房子. 为了简化问题,我们考虑这些事件发生在一个二维平面上.小A在平面上(0,0)点的位置,第i栋楼房可以用一条连接(i,0)和

TestDisk 数据恢复 重建分区表恢复文件-恢复diskpart clean

source:http://www.cgsecurity.org/wiki/TestDisk_CN TestDisk 是一款开源软件,受GNU General Public License (GPL v2+)条款保护. TestDisk:http://www.cgsecurity.org/wiki/TestDisk_CN TestDisk 是一款强大 的免费数据恢复软件! 早期主要是设计用来在使用有缺陷的软件,病毒或人为误操作(如不小心删除分区表)导致的分区丢失后,帮助用户恢复丢失分区,或修复不