bzoj4031 [HEOI2015]小Z的房间——矩阵树定理

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4031

矩阵树定理的模板题(第一次的矩阵树定理~);

有点细节,放在注释里了。

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long ll;
int const mod=1e9;
int n,m,a[105][105],d[105][105],sid[105][105],tot,num[3][15];
ll ans=1;
void add(int x,int y)
{
    d[x][x]++; d[y][y]++;
    sid[x][y]=1; sid[y][x]=1;
}
void gauss()
{
    int fl=0;
    for(int i=1;i<=tot;i++)
    {
        int nw=i;//
        for(int j=i+1;j<=tot;j++)
            if(a[j][i]>a[nw][i])nw=j;
        if(nw!=i)
        {
            fl^=1;
            for(int j=i;j<=tot;j++)swap(a[i][j],a[nw][j]);
        }
        for(int j=i+1;j<=tot;j++)//上三角而非对角线 
            while(a[j][i])
            {
                ll tmp=a[i][i]/a[j][i];
                for(int k=i;k<=tot;k++)
                {
                    ll tp=a[i][k]; a[i][k]=a[j][k];
                    a[j][k]=((tp-a[j][k]*tmp)%mod+mod)%mod;
                }
                fl^=1;
            }
        (ans*=a[i][i])%=mod;
    } 
    if(fl)ans=-ans;
    ans=((ans%mod)+mod)%mod;
}
int main()
{
    scanf("%d%d",&n,&m);
    char ch[3][15];
    for(int i=1;i<=n;i++)
    {
        int nw=i%2,pr=!nw;
        scanf("%s",ch[nw]+1);
        for(int j=1;j<=m;j++)
        {
            if(ch[nw][j]=='*')continue;//!!!
            tot++; num[nw][j]=tot;
            if(ch[nw][j-1]=='.')add(tot,num[nw][j-1]);
            if(ch[pr][j]=='.')add(tot,num[pr][j]);
        }
    }
    for(int i=1;i<=tot;i++)
        for(int j=1;j<=tot;j++)
            a[i][j]=(d[i][j]-sid[i][j]+mod)%mod;
    tot--;//
    gauss();
    printf("%lld",ans);
    return 0;
}

 

posted @ 2018-07-01 22:48  Zinn  阅读(140)  评论(0编辑  收藏  举报