zoukankan      html  css  js  c++  java
  • BZOJ 1016 [JSOI2008]最小生成树计数(kruskal + dfs)

    题意:

    求最小生成树的个数

    思路:

    网上很多题解都是矩阵树,

    由克鲁斯卡尔的步骤可以知道mst的每一种边权选的条数是固定的,所以我们dfs具体每种权值选哪几条并不会成环的方案数,相乘即可

    dfs是参考网上的,我是不会的


    代码:

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #include<string>
    #include<stack>
    #include<queue>
    #include<deque>
    #include<set>
    #include<vector>
    #include<map>
    #include<functional>
        
    #define fst first
    #define sc second
    #define pb push_back
    #define mem(a,b) memset(a,b,sizeof(a))
    #define lson l,mid,root<<1
    #define rson mid+1,r,root<<1|1
    #define lc root<<1
    #define rc root<<1|1
    #define lowbit(x) ((x)&(-x)) 
    
    using namespace std;
    
    typedef double db;
    typedef long double ldb;
    typedef long long ll;
    typedef unsigned long long ull;
    typedef pair<int,int> PI;
    typedef pair<ll,ll> PLL;
    
    const db eps = 1e-6;
    const int mod = 998244353;
    const int maxn = 2e6+100;
    const int maxm = 2e6+100;
    const int inf = 0x3f3f3f3f;
    const db pi = acos(-1.0);
    
    int fa[1000 + 10];
    struct Edge{
        int u, v, w;
    }edge[1000 + 10];
    struct Node{
        int l ,r, num;
    }node[1000 + 10];
    int find(int x){
        return fa[x]==x?x:find(fa[x]);
    }
    
    bool cmp(Edge a, Edge b){
        return a.w < b.w;
    }
    int tol;
    int n, m;
    int cnt = 0;
    ll sum = 0;
    
    void init(){
        for(int i = 1; i <= n; i++){
            fa[i] = i;
        }
        return;
    }
    
    void dfs(int nodeid, int edgeid, int num){
        if(edgeid > node[nodeid].r){
            if(num==node[nodeid].num)sum++;
            return;
        }
        int u = edge[edgeid].u;
        int v = edge[edgeid].v;
        int t1 = find(u);
        int t2 = find(v);
        if(t1 != t2){
            fa[t1]=t2;
            dfs(nodeid, edgeid+1, num+1);//选这条边
            fa[t1]=t1; //改回去
            fa[t2]=t2;
        }
        dfs(nodeid, edgeid+1, num); //不选这条边
        return;
    }
    
    int main(){
        scanf("%d %d", &n, &m);
        for(int i = 1; i <= m; i++){
            scanf("%d %d %d", &edge[i].u, &edge[i].v, &edge[i].w);
        }
        sort(edge + 1, edge + 1 + m, cmp);
        ll ans = 1;
        init();
        tol = 0;
        cnt = 0;
        for(int i = 1; i <= m; i++){
            if(i==1 || edge[i].w != edge[i-1].w){
                node[cnt++].r = i-1;
                node[cnt].l = i;
                node[cnt].num = 0;
            }
            int u = edge[i].u;
            int v = edge[i].v;
            int t1 = find(u);
            int t2 = find(v);
            if(t1 != t2){
                fa[t1] = t2;
                node[cnt].num++;
                tol++;
            }
        }
        node[cnt].r = m;
        if(tol != n-1){
            printf("0");
            return 0;
        }
        init();
        for(int i = 1; i <= cnt; i++){
            sum = 0;
            dfs(i, node[i].l, 0);
            ans*=sum;
            ans%=31011;
    
            //最后是改回去的,所以得把这个权值的连回来
            for(int j = node[i].l; j <= node[i].r; j++){
                int u = edge[j].u;
                int v = edge[j].v;
                int t1 = find(u);
                int t2 = find(v);
                if(t1 != t2){
                    fa[t1] = t2;
                }
            }
        }
        printf("%lld
    ", ans);
        return 0;
    
    }
    /*
    10
    1 3 5 -1 5 7 -5 9 -1 1
    
    9
    2 3 5 2 1 6 4 2 3
     */
  • 相关阅读:
    etl接口测试总结
    LR controller 参数化
    Mysql导入导出命令
    mysql基本命令
    mysql用户管理(新增用户及权限管理)
    源码编译搭建LAMP
    【OpenGL】Shader实例分析(一)-Wave
    仿真树叶飘落效果的实现(精灵旋转、翻转、钟摆运动等综合运用)
    cocos2d-x游戏开发(十四)用shader使图片背景透明
    泰然发布了一系列 OpenGL3.0 的教程,推荐大家参考学习
  • 原文地址:https://www.cnblogs.com/wrjlinkkkkkk/p/9833305.html
Copyright © 2011-2022 走看看