zoukankan      html  css  js  c++  java
  • 【BZOJ 1016】 1016: [JSOI2008]最小生成树计数 (DFS|矩阵树定理)

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

    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

    HINT

    Source

    【分析】

      不知道结论是不可以做的吧?表示也不会矩阵树定理。。dfs方法也要知道一些证明才能说明其准确性。

      【以后的博客都要留坑了?

      安利两种题解:

      1、我的打法:(不看都不知道为什么这样做是对的)

      https://blog.sengxian.com/solutions/bzoj-1016

      http://www.cnblogs.com/lcf-2000/p/5575412.html

      2、矩阵树(没打这种,还不会)

      http://blog.csdn.net/jarily/article/details/8902509

     1 #include<cstdio>
     2 #include<cstdlib>
     3 #include<cstring>
     4 #include<iostream>
     5 #include<algorithm>
     6 using namespace std;
     7 #define Maxn 1100
     8 #define Maxm 10100
     9 #define Mod 31011
    10 
    11 struct node
    12 {
    13     int x,y,c;
    14 }t[Maxm];
    15 
    16 bool cmp(node x,node y) {return x.c<y.c;}
    17 int a[Maxm],l[Maxm],r[Maxm],fa[Maxn];
    18 
    19 int ffa(int x)
    20 {
    21      return x==fa[x]?x:ffa(fa[x]);
    22 }
    23 
    24 int ct;
    25 void ffind(int x,int nw,int h)
    26 {
    27     if(nw==r[x]+1)
    28     {
    29         if(h==a[x]) ct++;
    30         return;
    31     }
    32     int x1=ffa(t[nw].x),x2=ffa(t[nw].y);
    33     if(x1!=x2)
    34     {
    35         fa[x1]=x2;
    36         ffind(x,nw+1,h+1);
    37         fa[x1]=x1;
    38     }
    39     ffind(x,nw+1,h);
    40 }
    41 
    42 int main()
    43 {
    44     int n,m;
    45     scanf("%d%d",&n,&m);
    46     for(int i=1;i<=m;i++)
    47     {
    48         scanf("%d%d%d",&t[i].x,&t[i].y,&t[i].c);
    49     }
    50     sort(t+1,t+1+m,cmp);
    51     int cnt=0,tot=0;
    52     for(int i=1;i<=n;i++) fa[i]=i;
    53     for(int i=1;i<=m;i++)
    54     {
    55         if(i==1||t[i].c!=t[i-1].c)
    56         {
    57             r[cnt]=i-1;l[++cnt]=i;
    58             a[cnt]=0;
    59         }
    60         int x1=ffa(t[i].x),x2=ffa(t[i].y);
    61         if(x1!=x2)
    62         {
    63             fa[x1]=x2;
    64             a[cnt]++;
    65             tot++;
    66         }
    67         
    68     }r[cnt]=m;
    69     if(tot!=n-1) printf("0
    ");
    70     else
    71     {
    72         for(int i=1;i<=n;i++) fa[i]=i;
    73         int ans=1;
    74         for(int i=1;i<=cnt;i++)
    75         {
    76             ct=0;
    77             ffind(i,l[i],0);
    78             ct%=Mod;
    79             ans=ans*ct;ans%=Mod;
    80             for(int j=l[i];j<=r[i];j++)
    81             {
    82                 int x1=ffa(t[j].x),x2=ffa(t[j].y);
    83                 if(x1!=x2) fa[x1]=x2;
    84             }
    85         }
    86         printf("%d
    ",ans);
    87     }
    88     return 0;
    89 }
    View Code

    2017-02-28 13:58:04

  • 相关阅读:
    Java三大特殊类
    静态顺序表and动态顺序表(一)_插入操作
    模拟实现memcpy、memmove函数
    模拟实现strcpy函数
    模拟实现Strlen函数
    数组相关知识总结(一)
    C语言学习总结(二)__操作符
    受控组件 & 非受控组件
    SyntheticEvent
    ReactDOM & DOM Elements
  • 原文地址:https://www.cnblogs.com/Konjakmoyu/p/6478555.html
Copyright © 2011-2022 走看看