zoukankan      html  css  js  c++  java
  • 最小生成树计数 BZOJ 1016

    最小生成树计数

    【问题描述】

    现在给出了一个简单无向加权图。你不满足于求出这个图的最小生成树,而希望知道这个图中有多少个不同的最小生成树。(如果两颗最小生成树中至少有一条边不同,则这两个最小生成树就是不同的)。由于不同的最小生成树可能很多,所以你只需要输出方案数对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的模就可以了。

    【样例输入】

    4 6

    1 2 1

    1 3 1

    1 4 1

    2 3 2

    2 4 1

    3 4 1

    【样例输出】

    8


    题解:

    1.用克鲁斯卡尔求一遍最小生成树,统计出某一权值在最小生成树中的个数(即所有权值相同的边的个数)

    2.考虑对于每一种权值的方案(Dfs)

    要求:

    (1)选出的边数等于最小生成树中该权值拥有的边数

    原理:最小生成树中每种权值的边数不变

    (2)不含环,判断是否有环可以用不压缩路径的并查集处理

    原理:树中不含环

    3.将所有权值的方案相乘

    原理:在最小生成树中对于每一种权值的合法方案构建出的图的连通情况相同

      1 #include<algorithm>
      2 #include<iostream>
      3 #include<cstring>
      4 #include<cstdlib>
      5 #include<cstdio>
      6 #include<cmath>
      7 using namespace std;
      8 inline int Get()
      9 {
     10     int x = 0, s = 1;
     11     char c = getchar();
     12     while('0' > c || c > '9')
     13     {
     14         if(c == '-') s = -1;
     15         c = getchar();
     16     }
     17     while('0' <= c && c <= '9')
     18     {
     19         x = (x << 3) + (x << 1) + c - '0';
     20         c = getchar();
     21     }
     22     return x * s;
     23 }
     24 struct shape
     25 {
     26     int x, y, z;
     27 };
     28 shape a[100233];
     29 int n, m, k;
     30 int tot;
     31 int cnt;
     32 int sum;
     33 int l[100233];
     34 int r[100233];
     35 int s[100233];
     36 int fat[100233];
     37 int c[100233];
     38 int u[100233];
     39 inline bool rule(shape a, shape b)
     40 {
     41     return a.z < b.z;
     42 }
     43 int Find(int x)
     44 {
     45     while(fat[x] != x) x = fat[x];
     46     return x;
     47 }
     48 void Dfs(int fig, int va, int le)
     49 {
     50     if(fig == s[va])
     51     {
     52         sum = (sum + 1) % 31011;
     53         if(sum == 1)
     54             for(int i = 0; i <= c[0]; ++i)
     55                 u[i] = c[i];
     56 //        for(int i = 1; i <= c[0]; ++i) printf("%d ", c[i]);
     57 //        cout<<endl;
     58         return;
     59     }
     60     for(int i = le; i <= r[va]; ++i)
     61     {
     62         int x = Find(a[i].x);
     63         int y = Find(a[i].y);
     64         int cx = fat[x];
     65         if(x == y) continue;
     66         fat[x] = y;
     67         c[++c[0]] = i;
     68         Dfs(fig + 1, va, i + 1);
     69         fat[x] = cx;
     70         --c[0];
     71     }
     72 }
     73 int main()
     74 {
     75     n = Get(), m = Get();
     76     for(int i = 1; i <= m; ++i)
     77     {
     78         a[i].x = Get();
     79         a[i].y = Get();
     80         a[i].z = Get();
     81     }
     82     sort(a + 1, a + 1 + m, rule);
     83     for(int i = 1; i <= n; ++i) fat[i] = i;
     84     for(int i = 1; i <= m; ++i)
     85     {
     86         if(a[i].z != a[i - 1].z)
     87         {
     88             r[tot] = i - 1;
     89             ++tot;
     90             l[tot] = i;
     91         }
     92         if(k != n - 1)
     93         {
     94             int x = Find(a[i].x), y = Find(a[i].y);
     95             if(x != y)
     96             {
     97                 fat[x] = y;
     98                 ++s[tot];
     99                 ++k;
    100             }
    101         }
    102     }
    103     if(k != n - 1)
    104     {
    105         printf("0");
    106         return 0;
    107     }
    108     r[tot] = m;
    109     for(int i = 1; i <= n; ++i) fat[i] = i;
    110     int ans = 1;
    111     for(int i = 1; i <= tot; ++i)
    112         if(s[i])
    113         {
    114             sum = 0;
    115             Dfs(0, i, l[i]);
    116             for(int l = 1; l <= u[0]; ++l)
    117             {
    118                 int x = Find(a[u[l]].x);
    119                 int y = Find(a[u[l]].y);
    120                 fat[x] = y;
    121             }
    122             ans = (ans * sum) % 31011;
    123         }
    124     printf("%d", ans);
    125 }
  • 相关阅读:
    吴裕雄--天生自然 R语言开发学习:高级编程
    吴裕雄--天生自然 R语言开发学习:使用ggplot2进行高级绘图(续二)
    吴裕雄--天生自然 R语言开发学习:使用ggplot2进行高级绘图(续一)
    吴裕雄--天生自然 R语言开发学习:使用ggplot2进行高级绘图
    吴裕雄--天生自然 R语言开发学习:处理缺失数据的高级方法(续一)
    吴裕雄--天生自然 R语言开发学习:处理缺失数据的高级方法
    吴裕雄--天生自然 R语言开发学习:分类(续二)
    2018年阿里云NoSQL数据库大事盘点
    就差这2块钱的安全投入,让这家企业损失了1977万!
    如何打造7*24h持续交付通道?阿里高级技术专家的5点思考
  • 原文地址:https://www.cnblogs.com/lytccc/p/6245061.html
Copyright © 2011-2022 走看看