• 【JSOI 2008】 最小生成树计数


    【题目链接】

               点击打开链接

    【算法】

              笔者做这题参考了这篇博客 :

              https://blog.sengxian.com/solutions/bzoj-1016

              推荐阅读

              首先,我们需要知道三个定理 :

              定理1 : 若A,B是两棵不同的最小生成树,它们的权值从小到大排列分别为 :

                            W(a1),W(a2),W(a3)....W(an-1)

                            W(b1),W(b2),W(b3)....W(bn-1)

                            那么,对于任意的i,都有W(ai) = W(bi)

              定理2 : 当最小生成树中所有w <= w0的边被加入后,图的联通性唯一

              定理3 : 若A是一棵最小生成树,A中权值为v的边有k条,那么,用任意k条权值为v的边替换A中权值为v的边且不产生

                            环的方案都是一棵最小生成树

             证明详见笔者推荐的那篇博客

             有了这三个定理,这题就很好做啦! 首先,任意求一棵最小生成树,记录每种权值的边出现的次数,然后,对每种

              权值的边做一遍深度优先搜索DFS,求出方案数,然后乘法原理,即可

    【代码】

                注意因为进行DFS时需要回溯,所以,并查集不能路径压缩

    #include<bits/stdc++.h>
    using namespace std;
    #define MAXN 110
    #define MAXM 1010
    const int MOD = 31011;
    
    int n,m,i,j,ans = 1,pos,len,sum,sx,sy;
    int fa[MAXN],s[MAXN],val[MAXN],l[MAXN],r[MAXN];
    
    struct Edge
    {
            int u,v,w;
    } e[MAXM];
    inline void init(int n)
    {
            int i;
            for (i = 1; i <= n; i++) fa[i] = i;
    }
    int get_root(int x)
    {
            if (fa[x] == x) return x;
            return get_root(fa[x]);
    }    
    
    bool cmp(Edge a,Edge b)
    {
            return a.w < b.w;
    }
    bool kruskal()
    {
            int i,cnt = 0,sx,sy;
            for (i = 1; i <= m; i++)
            {
                    sx = get_root(e[i].u);
                    sy = get_root(e[i].v);
                    if (e[i].w == val[len]) r[len]++;
                    if (sx != sy)
                    {
                            fa[sx] = sy;
                            cnt++;
                            if (e[i].w == val[len]) s[len]++;
                            else
                            {
                                    len++;
                                    l[len] = r[len] = i;
                                    s[len]++;
                                    val[len] = e[i].w;
                            }
                    }
            }            
            return cnt == n - 1;    
    }
    inline void dfs(int now,int r,int c)
    {
            int sx,sy;
            if (now > r)
            {
                    if (c == s[pos]) sum++;
                    return;
            }
            dfs(now+1,r,c);
            sx = get_root(e[now].u);
            sy = get_root(e[now].v);
            if (sx != sy) 
            {
                    fa[sx] = sy;
                    dfs(now+1,r,c+1);
                    fa[sx] = sx;
            }
    }
    
    int main() {
            
            scanf("%d%d",&n,&m);
            for (i = 1; i <= m; i++) scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
            sort(e+1,e+m+1,cmp);
            init(n);
            if (!kruskal())
            {
                    puts("0");
                    return 0;
            }
            init(n);
            for (i = 1; i <= len; i++)
            {
                    sum = 0;
                    pos = i;
                    dfs(l[i],r[i],0);
                    ans = (ans * sum) % MOD;
                    for (j = l[i]; j <= r[i]; j++)
                    {
                            sx = get_root(e[j].u);
                            sy = get_root(e[j].v);
                            if (sx != sy) fa[sx] = sy;        
                    }                    
            }
            printf("%d
    ",ans);
            
            return 0;
        
    }
  • 相关阅读:
    Nacos 1.3.0版本部署连接mysql 8+
    Java Certificate证书问题
    UIKit之浅析UIButton
    Xcode Coule not launch "aaa" press launch failed:timed out waiting for app launch
    Cocos2d-x 安装教程for mac(Xcode)
    关于继承UITableViewController若干问题
    Table的分割线偏移量设置 及其 UIEdgeInset详解
    retain、strong、weak、assign区别
    iOS 使用xib创建cell的两种初始化方式
    No architectures to compile for (ONLY_ACTIVE_ARCH=YES, active arch=x86_64, VALID_ARCHS=armv7 armv7s)
  • 原文地址:https://www.cnblogs.com/evenbao/p/9196317.html
Copyright © 2020-2023  润新知