题目描述:
给出 N*N 条边可能相连的概率
请计算仍能通行的道路恰有N-1条,且能联通所有城市的概率
题目分析:
矩阵树定理?
邻接矩阵中的的权可以不是1,而是其他权值,比如概率.
如果我们就把概率填进去 答案是肯定不对的…
这样计算出来的就是所有生成树的概率和,即
∑TΠe∈TPe
∑
T
Π
e
∈
T
P
e
而题目上要求的是恰有N-1条通行的道路…
∑TΠe∈TPeΠe∉T(1−Pe)
∑
T
Π
e
∈
T
P
e
Π
e
∉
T
(
1
−
P
e
)
令
G(i,j)=P(i,j)(1−P(i,j))
G
(
i
,
j
)
=
P
(
i
,
j
)
(
1
−
P
(
i
,
j
)
)
令
G(i,i)=−∑i!=jG(i,j)
G
(
i
,
i
)
=
−
∑
i
!
=
j
G
(
i
,
j
)
令
tmp=Π(1−pi)
t
m
p
=
Π
(
1
−
p
i
)
对G求n-1阶的行列式值
即
Det(Gn−1)=∑TΠe∈TPe(1−Pe)
D
e
t
(
G
n
−
1
)
=
∑
T
Π
e
∈
T
P
e
(
1
−
P
e
)
tmp∗Det(Gn−1)=Πe(1−pe)∑TΠe∈TPe(1−Pe)=∑TΠe(1−pe)Πe∈TPe(1−Pe)=∑TΠe∈TPeΠe∉T(1−Pe)
t
m
p
∗
D
e
t
(
G
n
−
1
)
=
Π
e
(
1
−
p
e
)
∑
T
Π
e
∈
T
P
e
(
1
−
P
e
)
=
∑
T
Π
e
(
1
−
p
e
)
Π
e
∈
T
P
e
(
1
−
P
e
)
=
∑
T
Π
e
∈
T
P
e
Π
e
∉
T
(
1
−
P
e
)
为了防止 tmp变成 0 我们需要对 输入的数据进行精度操作…
高斯消元里也要搞一下精度问题…
题目链接:
Ac 代码:
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstring>
const double eps=1e-10;
const int maxm=201;
double a[maxm][maxm];
inline double Gauss(int n)
{
double ret=1.0;
for(int i=1;i<=n;i++)
{
int k=i;
for(int j=i+1;j<=n;j++) if(std::fabs(a[k][i])<std::fabs(a[j][i])) k=j;
if (fabs(a[k][i])<eps) return 0.0;
if(k!=i)
{
for(int j=i;j<=n;j++) std::swap(a[k][j],a[i][j]);
ret=-ret;
}
for(int j=i+1;j<=n;j++)
{
double t=a[j][i]/a[i][i];
for(k=i;k<=n;k++)
a[j][k]=(a[j][k]-a[i][k]*t);
}
ret*=a[i][i];
}
return std::fabs(ret);
}
int n,m;
int main()
{
double tmp=1.0;
scanf("%d",&n);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
scanf("%lf",&a[i][j]);
if(eps+a[i][j]>1.0) a[i][j]-=eps;
if(i<j) tmp*=(1-a[i][j]);
a[i][j]/=(1.0-a[i][j]);
}
for(int i=1;i<=n;i++)
{
double sum=0.0;
for(int j=1;j<=n;j++)
sum+=a[i][j];
a[i][i]=-sum;
}
printf("%.10lf\n",Gauss(n-1)*tmp);
return 0;
}