• Bzoj1016 最小生成树计数


    Time Limit: 1000MS   Memory Limit: 165888KB   64bit IO Format: %lld & %llu

    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

    JSOI2008

    kruskal算法的改版。

    首先按照kruskal的思想做最小生成树,但是处理的时候,把所有边权相同的边记录下来,分进一组。

    之后试着从每组里dfs选边,使整张图连通,在这个过程中就可以统计出方案数

    读入的边出入点要离散化。注意数组范围。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 #include<cmath>
     5 #include<cstring>
     6 using namespace std;
     7 const int mxn=10000;
     8 int n,m;
     9 int sum;
    10 int ans=1;
    11 //
    12 struct edge{//
    13     int x,y;
    14     int v;
    15 }e[mxn];
    16 struct segment{
    17     int st,ed;//区块起止点 
    18     int v;
    19 }se[mxn];
    20 int cnt;
    21 int cmp(const edge a,const edge b){
    22     return a.v<b.v;
    23 }
    24 //
    25 int fa[mxn]; 
    26 int find(int x){
    27     if(fa[x]==x)return x;
    28     return find(fa[x]);//不可压缩 
    29 }
    30 //
    31 void dfs(int x,int now,int t){//x 组编号   now现在处理的边编号  t使用的边编号 
    32     if(now==se[x].ed+1){
    33         if(t==se[x].v)sum++;
    34         return;
    35     }
    36     int u=find(e[now].x),v=find(e[now].y);
    37     if(u!=v){
    38         fa[u]=v;
    39         dfs(x,now+1,t+1);//选用这条边 
    40         fa[u]=u;fa[v]=v;//还原状态 
    41     }
    42     dfs(x,now+1,t);//不选这条边 
    43     return;
    44 }
    45 
    46 int main(){
    47     scanf("%d%d",&n,&m);
    48     int i,j;
    49     for(i=1;i<=n;i++)fa[i]=i;//初始化并查集,处理边的连通 
    50     for(i=1;i<=m;i++)
    51         scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].v);
    52     sort(e+1,e+m+1,cmp);
    53     int tot=0;//联通边数 
    54     for(i=1;i<=m;i++){
    55         if(e[i].v!=e[i-1].v){//如果权值与之前不同 
    56             se[cnt].ed=i-1;se[++cnt].st=i;//分到新的一组 
    57         }
    58         int u=find(e[i].x);
    59         int v=find(e[i].y);
    60         if(u!=v){fa[u]=v;se[cnt].v++;tot++;}
    61     }
    62     se[cnt].ed=m;
    63     if(tot!=n-1){printf("0");return 0;}//未联通
    64     for(i=1;i<=n;i++)fa[i]=i;//初始化并查集,处理边组的连通
    65     for(i=1;i<=cnt;i++){
    66         sum=0;
    67         dfs(i,se[i].st,0);
    68         ans=(ans*sum)%31011;
    69         for(j=se[i].st;j<=se[i].ed;j++){
    70             int u=find(e[j].x),v=find(e[j].y);
    71             if(u!=v)fa[u]=v;
    72         }
    73     }
    74     printf("%d",ans%31011);
    75     return 0;
    76 }
  • 相关阅读:
    Hive 复杂数据类型的使用
    Hive 函数之内置运算符
    Hive中Join的类型和用法
    Hive 文件格式 & Hive操作(外部表、内部表、区、桶、视图、索引、join用法、内置操作符与函数、复合类型、用户自定义函数UDF、查询优化和权限控制)
    初步认识Hive
    Hadoop之MapReduce
    我理解中的Hadoop HDFS分布式文件系统
    Hadoop环境搭建 (伪分布式搭建)
    Hadoop(初始Hadoop)
    【数据库】MySQL 从安装到命令
  • 原文地址:https://www.cnblogs.com/SilverNebula/p/5665187.html
Copyright © 2020-2023  润新知