• bzoj 1016 最小生成树计数


    题目大意:

    现在给出了一个简单无向加权图 求这个图中有多少个不同的最小生成树

    如果两颗最小生成树中至少有一条边不同,则这两个最小生成树就是不同的

    输出方案数对31011的模

    思路:

    首先我们求出这个最小生成树需要用的边,每种边权的边需要用多少个

    然后因为注意到数据很小

    可以直接dfs

    对于每种权值的边dfs,求出该种权值的边满足最小生成树的方案有多少个

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 #include<cmath>
     5 #include<cstdlib>
     6 #include<cstring>
     7 #include<queue>
     8 #include<map>
     9 #include<vector>
    10 #define ll long long
    11 #define inf 2147483611
    12 #define MAXN 110
    13 #define MOD 31011
    14 using namespace std;
    15 inline int read()
    16 {
    17     int x=0,f=1;char ch=getchar();
    18     while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    19     while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
    20     return x*f;
    21 }
    22 struct data
    23 {
    24     int u,v,val;
    25     bool operator < (const data &a) const
    26     {
    27         return val<a.val;
    28     }
    29 }e[MAXN*20];
    30 struct edge {int l,r,num;}g[MAXN*20];
    31 int n,m,cnt,f[MAXN],kd,ans,res;
    32 void add(int u,int v,int w) {e[++cnt].u=u,e[cnt].v=v,e[cnt].val=w;}
    33 int find(int x,bool k)
    34 {
    35     if(x==f[x]) return x;
    36     if(k) return f[x]=find(f[x],1);
    37     else return find(f[x],0);
    38 }
    39 bool ok(int u,int v,int k)
    40 {
    41     int fa=find(u,k),fb=find(v,k);
    42     if(fa==fb) return 1;
    43     else {f[fa]=fb;return 0;}
    44 }
    45 bool kruskal()
    46 {
    47     cnt=0;
    48     for(int i=1;i<=m;i++)
    49     {
    50         if(e[i].val!=e[i-1].val) g[kd].r=i-1,g[++kd].l=i;
    51         if(!ok(e[i].u,e[i].v,1)) cnt++,g[kd].num++;
    52     }
    53     g[kd].r=m;
    54     if(cnt<n-1) return 0;
    55     else return 1;
    56 }
    57 void dfs(int k,int pos,int v)
    58 {
    59     if(pos==g[k].r+1) {if(v==g[k].num) res++;return ;}
    60     int t=find(e[pos].u,0);
    61     if(!ok(e[pos].u,e[pos].v,0))
    62     {
    63         dfs(k,pos+1,v+1);
    64         f[t]=t;
    65     }
    66     dfs(k,pos+1,v);
    67 }
    68 int main()
    69 {
    70     n=read(),m=read();
    71     int a,b,c;
    72     for(int i=1;i<=m;i++) {a=read(),b=read(),c=read();add(a,b,c);}
    73     for(int i=1;i<=n;i++) f[i]=i;
    74     sort(e+1,e+m+1);
    75     if(!kruskal()) {printf("0");return 0;}
    76     for(int i=1;i<=n;i++) f[i]=i;
    77     ans=1;
    78     for(int i=1;i<=kd;i++)
    79     {
    80         res=0;
    81         dfs(i,g[i].l,0);
    82         (ans*=res%MOD)%=MOD;
    83         for(int j=g[i].l;j<=g[i].r;j++) ok(e[j].u,e[j].v,1);
    84     }
    85     printf("%d",ans);
    86 }
    View Code
  • 相关阅读:
    python3 操作excel(读操作)
    display:inline-block;产生间隙解决方法
    vedio自定义样式
    angularjs路由
    移动端设置字体px转换rem的脚本
    div在不固定高度的情况下垂直或者水平居中
    css气泡地址和分享地址
    js点击按钮div显示,点击div或者body和按钮,div隐藏
    js倒计时跳转页面
    点击按钮div显示,点击div或者document,div隐藏
  • 原文地址:https://www.cnblogs.com/yyc-jack-0920/p/7872980.html
Copyright © 2020-2023  润新知