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

    题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1016

    首先要知道最小生成树的性质:不管这个最小生成树如何构成,同样权值的边的个数是不变的。

    所以讲每条边按权值排序,并记录最小生成树中该类权值的个数,然后爆搜。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn = 6e6 + 10;
    const int mod = 31011;
    struct node {
        int s, e, w;
    }q[maxn];
    struct qujian {
        int l, r, val;
    }a[maxn];
    int fa[maxn];
    int Find(int x) {
        return x == fa[x] ? fa[x] : Find(fa[x]);
    }
    bool cmp(node a, node b) {
        return a.w < b.w;
    }
    int sum;
    void dfs(int x, int now, int k) {
        if (now == a[x].r + 1) {
            if (k == a[x].val)
                sum++;
            return;
        }
        int xx = Find(q[now].s);
        int yy = Find(q[now].e);
        if (xx != yy) {
            fa[xx] = yy;
            dfs(x, now + 1, k + 1);
            fa[xx] = xx, fa[yy] = yy;
        }
        dfs(x, now + 1, k);
    }
    int main() {
        int n, m;
        scanf("%d%d", &n, &m);
        for (int i = 1; i <= n; i++)fa[i] = i;
        for (int i = 1; i <= m; i++)
            scanf("%d%d%d", &q[i].s, &q[i].e, &q[i].w);
        sort(q + 1, q + 1 + m, cmp);
        int cnt = 1, num = 0, ans = 1;
        for (int i = 1; i <= m; i++) {
            if (q[i].w != q[i - 1].w) {
                a[cnt++].r = i - 1;
                a[cnt].l = i;
            }
            int xx = Find(q[i].s);
            int yy = Find(q[i].e);
            if (xx != yy) {
                a[cnt].val++;
                fa[xx] = yy;
                num++;
            }
        }
        if (num != n - 1) {
            printf("0");
            return 0;
        }
        a[cnt].r = m;
        for (int i = 1; i <= n; i++)
            fa[i] = i;
        for (int i = 1; i <= cnt; i++) {
            sum = 0;
            dfs(i, a[i].l, 0);
            ans = ans * sum % mod;
            for (int j = a[i].l; j <= a[i].r; j++) {
                int xx = Find(q[j].s);
                int yy = Find(q[j].e);
                if (xx != yy)
                    fa[xx] = yy;
            }
        }
        printf("%d
    ", ans);
    }
  • 相关阅读:
    软件工程第一次结对作业
    软件工程第二次作业
    vue之vuex
    ceshi
    第3次 结构与部分
    第二次作业
    获得领跑衫感言
    期末总结
    第十四,十五周作业
    第七周作业
  • 原文地址:https://www.cnblogs.com/sainsist/p/11125997.html
Copyright © 2011-2022 走看看