zoukankan      html  css  js  c++  java
  • bzoj4596 [Shoi2016]黑暗前的幻想乡

    题目描述:

    bz

    luogu

    题解:

    容斥+矩阵树。

    考虑用其中$i$个人(没有每人一条路的限制)能组成的生成树的个数。

    所以$2^{n-1}$枚举然后$n^3$高消即可。

    高消常数小不虚。

    代码:

    #include<vector>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    const int N = 20;
    const int MOD = 1000000007;
    template<typename T>
    inline void read(T&x)
    {
        T f = 1,c = 0;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){c=c*10+ch-'0';ch=getchar();}
        x = f*c;
    }
    template<typename T>
    inline void Mod(T&x){if(x>=MOD)x-=MOD;}
    int fastpow(int x,int y)
    {
        int ret = 1;
        while(y)
        {
            if(y&1)ret=1ll*ret*x%MOD;
            x=1ll*x*x%MOD;y>>=1;
        }
        return ret;
    }
    int inv(int x){return fastpow(x,MOD-2);}
    struct Pair
    {
        int u,v;
        Pair(){}
        Pair(int u,int v):u(u),v(v){}
    };
    int n,a[N][N];
    vector<Pair>ve[N];
    int gs()
    {
        int ret = 1;
        for(int i=1;i<n;i++)
        {
            int tmp = i;
            while(tmp<n&&!a[tmp][i])tmp++;
            if(tmp==n)return 0;
            if(tmp!=i)
            {
                ret = MOD-ret;
                for(int j=i;j<n;j++)
                    swap(a[i][j],a[tmp][j]);
            }
            ret = 1ll*ret*a[i][i]%MOD;
            int now = inv(a[i][i]);
            for(int j=i;j<n;j++)
                a[i][j] = 1ll*a[i][j]*now%MOD;
            for(int j=i+1;j<n;j++)if(a[j][i])
            {
                now = a[j][i];
                for(int k = i;k<n;k++)
                    Mod(a[j][k] += MOD-1ll*now*a[i][k]%MOD);
            }
        }
        return ret;
    }
    int main()
    {
        read(n);
        for(int m,u,v,i=0;i<n-1;i++)
        {
            read(m);
            while(m--)
                read(u),read(v),ve[i].push_back(Pair(u,v));
        }
        int ans = 0;
        for(int i=0;i<(1<<(n-1));i++)
        {
            int f = (n&1?1:-1);memset(a,0,sizeof(a));
            for(int j=0;j<n-1;j++)if(i&(1<<j))
            {
                f = -f;
                for(int k=0,lim=ve[j].size();k<lim;k++)
                {
                    int u = ve[j][k].u,v = ve[j][k].v;
                    a[u][u]++,a[v][v]++;
                    Mod(a[u][v]+=MOD-1),Mod(a[v][u]+=MOD-1);
                }
            }
            int now = gs();
            Mod(ans += (f==1?now:MOD-now));
        }
        printf("%d
    ",ans);
        return 0;
    }
    View Code
  • 相关阅读:
    自动化测试如何解决验证码的问题
    python读取xml文件
    python实现简单爬虫功能
    python使用mysql数据库
    Prometheus 到底 NB 在哪里?- 每天5分钟玩转 Docker 容器技术(84)
    Prometheus 架构
    数据收集利器 cAdvisor
    Weave Scope 多主机监控
    Weave Scope 容器地图
    监控利器 sysdig
  • 原文地址:https://www.cnblogs.com/LiGuanlin1124/p/11132885.html
Copyright © 2011-2022 走看看