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

    1016: [JSOI2008]最小生成树计数

    Time Limit: 1 Sec  Memory Limit: 162 MB

    Description

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

    Input

      第一行包含两个数,n和m,其中1<=n<=100; 1<=m<=1000; 表示该无向图的节点数和边数。每个节点用1~n的整
    数编号。接下来的m行,每行包含两个整数:a, b, c,表示节点a, b之间的边的权值为c,其中1<=c<=1,000,000,0
    00。数据保证不会出现自回边和重边。注意:具有相同权值的边不会超过10条。

    Output

      输出不同的最小生成树有多少个。你只需要输出数量对31011的模就可以了。

    Sample Input

    4 6
    1 2 1
    1 3 1
    1 4 1
    2 3 2
    2 4 1
    3 4 1

    Sample Output

    8

    是一道对 kruskal 原理的考察

    考虑kruskal 算法的实现过程,我们先将边权排序, 然后从小到大加边

    可以发现,所有的最小生成树,每种权值的边的数量是一定了

    每次进行完一组相同权值的边的操作时,图的连通性是相同的

    ps: 假设在加入权值为 k 的边之前, 图的连通性相同, 每当我们通过存在一条权值为k的边时,对应的点必然会被加入到对应的集合中,所以连通性依然相同

    相同权值边数量小于10, 我们可以得到之前的状态,然后DFS枚举, 最后用乘法原理得到答案

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <algorithm>
      4 #include <cstring>
      5 #define LL long long 
      6 using namespace std;
      7 
      8 const int MAXN = 100 + 10, MAXM = 1e3 + 10;
      9 int cnt = 0;
     10 int tot = 0;
     11 int n, m;
     12 LL sum = 0;
     13 LL ans = 1;
     14 LL mod = 31011;
     15 int last = 1;
     16 int T = 0;
     17 int f[2 * MAXN];
     18 int flag[2 * MAXN];
     19 int exs[2 * MAXN];
     20 int father[2 * MAXN];
     21 int use[4 * MAXM];
     22 
     23 
     24 struct wa {
     25     int l, r;
     26     int num;
     27 } wait[4 * MAXM];
     28 struct edge {
     29     int u, v;
     30     int w;
     31 } e[MAXM * 4];
     32 
     33 void init()
     34 {
     35     for(int i = 1; i <= n; i++) {
     36         father[i] = i;
     37     }
     38 }
     39 
     40 int find(int x)
     41 {
     42     if(father[x] != x) {
     43         return find(father[x]);
     44     }
     45     return x;
     46 }
     47 
     48 inline LL read()
     49 {
     50     LL x = 0, w = 1; char ch = 0;
     51     while(ch < '0' || ch > '9') {
     52         if(ch == '-') {
     53             w = -1;
     54         }
     55         ch = getchar();
     56     }
     57     while(ch >= '0' && ch <= '9') {
     58         x = x * 10 + ch - '0';
     59         ch = getchar();
     60     }
     61     return x * w;
     62 }
     63 
     64 bool cmp(edge a, edge b)
     65 {
     66     return a.w < b.w;
     67 }
     68 
     69 /*bool judge(int last, int lim)
     70 {
     71     for(int i = 1; i <= tot; i++) {
     72         f[wait[i]] = wait[i];
     73     }
     74     for(int i = last; i <= lim; i++) {
     75         if(use[i]) {
     76             int x = find2(e[i].u), y = find2(e[i].v);
     77             if(x == y) {
     78                 return false;
     79             } else {
     80                 f[y] = x;
     81             }
     82         }
     83     }
     84     return true;
     85 }*/
     86 
     87 void cal(int k, int lim, int num, int T)
     88 {
     89     if(k == lim + 1) {
     90     //    cout<<num<<endl;
     91         if(num == T) {
     92             sum++;
     93         }
     94         return;
     95     }
     96     cal(k + 1, lim, num, T);
     97     int x = find(e[k].u), y = find(e[k].v);
     98     if(x != y) {
     99         father[y] = x;
    100         cal(k + 1, lim, num + 1, T);
    101         father[x] = x, father[y] = y;
    102     }
    103 }
    104 int main()
    105 {
    106     //freopen("award9.in", "r", stdin);
    107     //freopen("t.out", "w", stdout);
    108     n = read(), m = read();
    109     init();
    110     for(int i = 1; i <= m; i++) {
    111         e[i].u = read(), e[i].v = read(), e[i].w = read();
    112     }
    113     sort(e + 1,  e + m + 1, cmp);
    114     cnt = 0;
    115     for(int i = 1; i <= m; i++) {
    116         int x = find(e[i].u), y = find(e[i].v);
    117         if(x != y) {
    118             T++;
    119             father[x] = y;
    120             sum++;
    121         }
    122         if(e[i].w != e[i + 1].w) {
    123             wait[++cnt].l = last;
    124             wait[cnt].r = i;
    125             wait[cnt].num = T;
    126             T = 0;
    127             last = i + 1;
    128         }
    129     }
    130     if(sum < n - 1) {
    131         printf("0
    ");
    132         return 0;
    133     }
    134     init();
    135     for(int i = 1; i <= cnt; i++) {
    136         sum = 0;
    137         cal(wait[i].l, wait[i].r, 0, wait[i].num);
    138     //    cout<<wait[i].l<<" "<<wait[i].r<<" "<<wait[i].num<<endl;
    139     //    cout<<sum<<endl<<endl;
    140         for(int j = wait[i].l; j <= wait[i].r; j++) {
    141             int x = find(e[j].u), y = find(e[j].v);
    142             if(x != y) {
    143                 father[y] = x;
    144             }
    145         }    
    146         ans = ans * sum % mod;
    147     }
    148     printf("%lld
    ", ans);
    149 }
    View Code
  • 相关阅读:
    描述下jvm的gc机制,常用的jvm调优方法,oom如何产生,如何处理oom 问题?
    大数据hadoop 面试经典题
    redis 个人理解和常用命令以及应用场景
    Hadoop 源码编译 step by step 最简洁的步骤
    Openstack 的介绍 ,安装以及简单应用
    Docker 的介绍 ,安装以及简单应用
    星型模型和雪花模型的应用场景
    php向js的函数内传递参数-用经纬度计算2点间的距离
    php-URL方法下载远程图片
    微信开发-js接口的使用无法使用分享功能的一些说明
  • 原文地址:https://www.cnblogs.com/wuenze/p/8438153.html
Copyright © 2011-2022 走看看