zoukankan      html  css  js  c++  java
  • BZOJ 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
     

      这一次居然自己想出来了一道还算比较难的题,心里好开心O(∩_∩)O~~

      这道题用到了最小生成树的几个性质。第一,最小生成树每种边权的边数量一定。第二(由第一点可得),当一个图有多个最小生成树时,只可能由一条边替换掉一条等边权的边来得到一颗新的最小生成树。所以,注意到题目中的一个条件:

      具有相同权值的边不会超过10条。

      所以我们就非常地开心。因为这样就可以做了。我们把边按权值排序,然后对于每一块权值相同的边搜索哪些边要选,再统计一下方案数就可以AC辣!

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<cmath>
     6 #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
     7 #define maxn 5010
     8 #define INF (1LL<<50)
     9 #define mod 31011
    10 
    11 using namespace std;
    12 typedef long long llg;
    13 
    14 struct data{
    15     int u,v,x;
    16     bool operator < (const data &h)const{return x<h.x;}
    17 }s[maxn];
    18 struct dat1{
    19     int l,r,x;
    20     dat1(int a=0,int b=0,int c=0):l(a),r(b),x(c){};
    21 }ss[maxn];
    22 int n,m,fa[maxn],ls,la[maxn],w[maxn];
    23 llg ans=INF,a1,now,aa=1;
    24 bool ww[maxn];
    25 
    26 int getint(){
    27     int w=0,q=0;
    28     char c=getchar();
    29     while((c<'0'||c>'9')&&c!='-') c=getchar();
    30     if(c=='-') q=1,c=getchar();
    31     while(c>='0'&&c<='9') w=w*10+c-'0',c=getchar();
    32     return q?-w:w;
    33 }
    34 
    35 int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}
    36 
    37 inline void work(){
    38     now=0;int k=0;
    39     for(int i=1;i<=n;i++) fa[i]=i;
    40     for(int i=1,u,v;i<=m;i++)
    41         if(ww[i]){
    42             u=s[i].u;v=s[i].v;
    43             if(find(u)!=find(v)){
    44                 now+=s[i].x; k++;
    45                 fa[find(u)]=find(v);
    46             }
    47     }
    48     if(k!=n-1) return;
    49     if(now<ans) ans=now,a1=1;
    50     else if(now==ans) a1++;
    51 }
    52 
    53 void dfs(int res,int now,int dd){
    54     if(now==dd+1){
    55         work();return;
    56     }
    57     if(res){
    58         ww[now]=1;
    59         dfs(res-1,now+1,dd);
    60     }
    61     if(dd-now+1>res){
    62         ww[now]=0;
    63         dfs(res,now+1,dd);
    64     }
    65 }
    66 
    67 int main(){
    68     n=getint();m=getint();
    69     for(int i=1;i<=m;i++){
    70         s[i].u=getint();s[i].v=getint();
    71         s[i].x=getint();
    72     }
    73     sort(s+1,s+m+1);
    74     for(int i=1;i<=n;i++) fa[i]=i;
    75     for(int i=1,u,v;i<=m;i++){
    76         w[i]=w[i-1]; ww[i]=1;
    77         la[i]=i; u=s[i].u;v=s[i].v;
    78         if(s[i-1].x==s[i].x) la[i]=la[i-1];
    79         if(find(u)!=find(v)){
    80             now+=s[i].x; w[i]++;
    81             fa[find(u)]=find(v);
    82         }
    83         if(la[i]!=i && s[i+1].x!=s[i].x)
    84             ss[++ls]=dat1(la[i],i,w[i]-w[la[i]-1]);
    85     }
    86     for(int i=1;i<=ls;i++){
    87         ans=INF;
    88         dfs(ss[i].x,ss[i].l,ss[i].r);
    89         for(int j=ss[i].l;j<=ss[i].r;j++) ww[j]=1;
    90         aa*=a1; aa%=mod;
    91     }
    92     ans%=mod; aa%=mod;
    93     printf("%lld",aa);
    94     return 0;
    95 }
  • 相关阅读:
    树莓派设置CPU运行的核心数为3,保留核心4号
    node+egg中mongdb的一些知识点
    如何提高前端的技能和快速涨薪?
    【安全认证】我的CISSP达成之路
    前端gitLab ci/cd搭建
    flutter调试
    js rgb hex hsv色值转换
    Error waiting for a debug connection: The log reader stopped unexpectedly
    Flutter滑动列表实现
    前端异常监控
  • 原文地址:https://www.cnblogs.com/lcf-2000/p/5575412.html
Copyright © 2011-2022 走看看