• [JSOI2008]最小生成树计数


    这个题的思路主要有两种。。。本来博主以为自己的方法仅有自己胡。。。后来又翻到了有的大佬也这么写。。。

    代码实现比较简单。。。确定做法正确之后就很快就可以搞定了。。。哈~哈~哈~

    最小生成树满足两个性质:

    1.它一定是一棵树它一定有 n-1 条边。。。

    2.如果是最小的。。。那么优先选择权值小的边。。。

    这个地方只要小意会一下就可以了。。。可能有点绕。。。

    如果要保证这棵树的权值最小。。。

    那么所用的某种权值的边的数量是一定的。。。

    所以只要统计一下。。。

    题目又很友好的给出了提示具有相同权值的边不会超过10条。。。

    辣么我们只要对每种权值的边进行 dfs 判断它的方案数就可以了。。。

    呆码:

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #define mo 31011;
    using namespace std;
    
    int fa[1010],sum,n,m,cnt,tot;
    
    struct asd{
        int x,y;
        int dis;
    } a[1010];
    
    struct sdf{
        int l,r,num;
    } e[1010];
    
    inline int find(int x) { return x==fa[x] ? x : find(fa[x]); }
    
    inline void unionn(int x,int y) { fa[x]=y; }
    
    inline void unionu(int x,int y) { fa[x]=x; fa[y]=y; }
    
    inline bool cmp(asd x,asd y)
    {
        return x.dis<y.dis;
    }
    
    inline void dfs(int x,int now,int num)
    {
        if(now==e[x].r+1)
        {
            if(num==e[x].num) sum++;
            return;
        }
        int xx=find(a[now].x);
        int yy=find(a[now].y);
        if(xx!=yy)
        {
            unionn(xx,yy);
            dfs(x,now+1,num+1);
            unionu(xx,yy);
        }
        dfs(x,now+1,num);
    }
    
    int main()
    {
        cin>>n>>m;
        for(int i=1;i<=n;i++)
            fa[i]=i;
        for(int i=1;i<=m;i++)
            scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].dis);
        sort(a+1,a+1+m,cmp);
        for(int i=1;i<=m;i++)
        {
            if(a[i].dis!=a[i-1].dis)
                { e[++cnt].l=i; e[cnt-1].r=i-1; }
            int xx=find(a[i].x);
            int yy=find(a[i].y);
            if(xx!=yy)
            {
                unionn(xx,yy);
                e[cnt].num++;
                tot++;
            }
        }
        e[cnt].r=m;
        if(tot<n-1) { printf("0"); return 0; }
        for(int i=1;i<=n;i++)
            fa[i]=i;
        int ans=1;
        for(int i=1;i<=cnt;i++)
        {
            sum=0;
            dfs(i,e[i].l,0);
            ans=(ans*sum)%mo;
            for(int j=e[i].l;j<=e[i].r;j++)
            {
                int xx=find(a[j].x);
                int yy=find(a[j].y);
                if(xx!=yy) unionn(xx,yy);
            }
        }
        printf("%d",ans);
    }
    代码
  • 相关阅读:
    li float后IE下有空格
    [转]输入框对齐问题
    footer贴在底部的布局
    css3.0参考手册
    Java变量的命名规范
    刷题01
    前端面试题
    Cadence学习封装制作(焊盘)
    Cadence学习文档后缀简介
    Cadence学习PCB设计(序)
  • 原文地址:https://www.cnblogs.com/zzzyc/p/8821723.html
Copyright © 2020-2023  润新知