[BZOJ3534][SDOI2014]重建(矩陣樹定理)

題目:

我是超鏈接

題解:

矩陣樹定理,先前只知道構造方法和基本的求生成樹個數
然而實際上K矩陣是這麼個玩意
這裏寫圖片描述
我們可以發現其實是跟邊權有關的
其實矩陣樹定理求的是

TeTwe

然後這個題目讓我們求的顯然是
TeTpeeT(1pe)

這個式子求的前半截是一樣的,後半截不太一樣,但是顯然
eT(1pe)=e(1pe)eT(1pe)

然後就可以帶進去了
e(1pe)TeTpe1pe

然後我們就可以讓a的權值爲後面的一堆就好啦
還有就是當矩陣中出現 |a|<eps 時就 a=eps 當矩陣中出現 |1a|<eps 時就 a=1eps
BZOJ上的輸出一定要開到1e-10才能過= =

代碼:

#include <cstdio>
#include <cmath>
#include <iostream>
using namespace std;
const int N=55;
const double eps=1e-8;
double a[N][N];
double gauss(int n)
{
    double ans=1;
    for (int i=1;i<=n;i++)
    {
        int num=i;
        for (int j=i+1;j<=n;j++)
          if (abs(a[num][i])<abs(a[j][i])) num=j;
        if (num!=i) for (int j=i;j<=n;j++) swap(a[num][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;k++) a[j][k]-=t*a[i][k];
        }
        if (abs(a[i][i])<eps) return 0;
        ans=ans*a[i][i];
    }
    return abs(ans);
}
int main()
{
    int n;scanf("%d",&n);
    for (int i=1;i<=n;i++)
      for (int j=1;j<=n;j++)
        scanf("%lf",&a[i][j]);
    double tmp=1;
    for (int i=1;i<=n;i++)
      for (int j=1;j<=n;j++)
      {
        if (abs(a[i][j])<eps) a[i][j]=eps;
        else if (abs(1.0-a[i][j])<eps) a[i][j]=1.0-eps;
        if (i<j) tmp*=1.0-a[i][j];
        a[i][j]=a[i][j]/(1.0-a[i][j]);
      }
    for (int i=1;i<=n;i++)
    {
        a[i][i]=0;
        for (int j=1;j<=n;j++)
          if (i!=j) a[i][i]+=a[i][j],a[i][j]=-a[i][j];
    }
    printf("%.10lf",tmp*gauss(n-1));
}
發佈了722 篇原創文章 · 獲贊 547 · 訪問量 15萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章