zoukankan      html  css  js  c++  java
  • P4208 [JSOI2008]最小生成树计数

    ???这题竟然不是生成树计数?直接暴力就行。我们需要知道一个性质,就是最小生成树无论长成啥样,边权数量是一定的。然后用乘法原理一算就行啦。

    好像还有生成树计数的作法,太麻烦了,就不写了。

    题干:

    题目描述
    
    现在给出了一个简单无向加权图。你不满足于求出这个图的最小生成树,而希望知道这个图中有多少个不同的最小生成树。(如果两颗最小生成树中至少有一条边不同,则这两个最小生成树就是不同的)。由于不同的最小生成树可能很多,所以你只需要输出方案数对31011的模就可以了。
    输入输出格式
    输入格式:
    
    第一行包含两个数,n和m,其中1<=n<=100; 1<=m<=1000; 表示该无向图的节点数和边数。每个节点用1~n的整数编号。
    
    接下来的m行,每行包含两个整数:a, b, c,表示节点a, b之间的边的权值为c,其中1<=c<=1,000,000,000。
    
    数据保证不会出现自回边和重边。注意:具有相同权值的边不会超过10条。
    
    输出格式:
    
    输出不同的最小生成树有多少个。你只需要输出数量对31011的模就可以了。

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<ctime>
    #include<queue>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    #define duke(i,a,n) for(register int i = a;i <= n;++i)
    #define lv(i,a,n) for(register int i = a;i >= n;--i)
    #define clean(a) memset(a,0,sizeof(a))
    const int INF = 1 << 30;
    typedef long long ll;
    typedef double db;
    template <class T>
    void read(T &x)
    {
        char c;
        bool op = 0;
        while(c = getchar(), c < '0' || c > '9')
            if(c == '-') op = 1;
        x = c - '0';
        while(c = getchar(), c >= '0' && c <= '9')
            x = x * 10 + c - '0';
        if(op) x = -x;
    }
    template <class T>
    void write(T x)
    {
        if(x < 0) putchar('-'), x = -x;
        if(x >= 10) write(x / 10);
        putchar('0' + x % 10);
    }
    const int N = 2010;
    const int mod = 31011;
    struct node
    {
        int l,r,w;
    }e[N];
    int f[N];
    struct rdq
    {
        int left,right,va;
    }a[N];
    int m,n,cnt = 0,ans,sum = 0;
    bool cmp(node a,node b)
    {
        return a.w < b.w;
    }
    int find(int x)
    {
        if(f[x] == x)
        return x;
        else
        return find(f[x]);
    }
    void dfs(int x,int now,int k)
    {
        if(now == a[x].right + 1)
        {
            if(k == a[x].va)
            {
                sum++;
            }
            return;
        }
        int xx = find(e[now].l),yy = find(e[now].r);
        if(xx != yy)
        {
            f[xx] = yy;
            dfs(x,now + 1,k + 1);
            f[xx] = xx;
            f[yy] = yy;
        }
        dfs(x,now + 1,k);
    }
    int main()
    {
        read(n);read(m);
        duke(i,1,n)
            f[i] = i;
        duke(i,1,m)
        {
            read(e[i].l);read(e[i].r);read(e[i].w);
        }
        sort(e + 1,e + m + 1,cmp);
        int tot = 0;
        for(int i = 1;i <= m;++i)
        {
            if(e[i].w != e[i - 1].w) cnt++,a[cnt].left = i,a[cnt - 1].right = i - 1;
            int xx = find(e[i].l),yy = find(e[i].r);
            if(xx != yy)
            {
                f[xx] = yy;
                a[cnt].va ++;
                tot++;
            }
        }
        if(tot != n - 1)
        {
            printf("0
    ");
            return 0;
        }
        a[cnt].right = m;
        ans = 1;
        duke(i,1,n)
        f[i] = i;
        duke(i,1,cnt)
        {
            sum = 0;
            dfs(i,a[i].left,0);
            ans = (ans * sum) % mod;
            for(int j = a[i].left;j <= a[i].right;++j)
            {
                int xx = find(e[j].l),yy = find(e[j].r);
                if(xx != yy)
                {
                    f[xx] = yy;
                }
            }
        }
        printf("%d
    ",ans);
        return 0;
        
    }
  • 相关阅读:
    react项目中如何解决同时需要多个请求问题
    jq+ajax+bootstrap改写一个动态分页的表格
    Window7+vs2008+QT环境搭建
    mssql charindex
    解决NTLDR is missing,系统无法启动的方法
    基于三汇语音卡的呼叫中心开发(一)
    Wince 或Windows平台 C#调用Bitmap对象后资源应该如何释放
    Anki:插件开发
    java.lang.ClassNotFoundException: com.opensymphony.xwork2.util.ValueStack
    struts2中action之间的一种跳转
  • 原文地址:https://www.cnblogs.com/DukeLv/p/10519945.html
Copyright © 2011-2022 走看看