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


    Solution:

    Kruskal+并查集+暴搜

    对于每一个符合题意的最小生成树,其每一条树边必定满足:①边权值和一定②对于最小生成树上的每一种权值的边,其数量一定

    利用条件②,可以在每一种权值中dfs枚举所有情况,利用并查集判断待取边能否加入(因为回溯需要恢复状态,不能路径压缩)

    Code:

     1 #include <cstdio>
     2 #include <algorithm>
     3 #include <iostream>
     4 using namespace std;
     5 inline int read()
     6 {
     7     register int f=1,k=0;register char c=getchar();
     8     while (c<'0'||c>'9')c=='-'&&(f=-1),c=getchar();
     9     while (c>='0'&&c<='9')k=k*10+c-'0',c=getchar();
    10     return k*f;
    11 }
    12 const int maxn=1010,MOD=31011;
    13 int n,m,cnt,tot,ans=1,sum,fa[maxn];
    14 struct edge{int x,y,v;}e[maxn];
    15 struct data{int l,r,v;}a[maxn];
    16 int find(int now){return fa[now]==now?now:find(fa[now]);}
    17 bool cmp(edge a,edge b){return a.v<b.v;}
    18 void dfs(int x,int now,int k)
    19 {
    20     if (now==a[x].r+1)
    21     {
    22         if (a[x].v==k)sum++;
    23         return;
    24     }
    25     register int q=find(e[now].x),p=find(e[now].y);
    26     if (p!=q)
    27     {
    28         fa[q]=p;
    29         dfs(x,now+1,k+1);
    30         fa[p]=p;fa[q]=q;
    31     }
    32     dfs(x,now+1,k);
    33 }
    34 int main()
    35 {
    36     n=read();m=read();
    37     for (register int i=1;i<=n;i++)fa[i]=i;
    38     for (register int i=1;i<=m;i++)
    39     {
    40         e[i].x=read();e[i].y=read();e[i].v=read();
    41     }
    42     sort(e+1,e+1+m,cmp);
    43     for (register int i=1;i<=m;i++)
    44     {
    45         if (e[i].v!=e[i-1].v)a[++cnt].l=i,a[cnt-1].r=i-1;
    46         register int p=find(e[i].x),q=find(e[i].y);
    47         if (p!=q)
    48         {
    49             a[cnt].v++;
    50             fa[p]=fa[q];
    51             tot++;
    52         }
    53     }
    54     a[cnt].r=m;
    55     if (tot!=n-1)
    56     {
    57         printf("0
    ");
    58         return 0;
    59     }
    60     for (register int i=1;i<=n;i++)fa[i]=i;
    61     for (register int i=1;i<=cnt;i++)
    62     {
    63         sum=0;
    64         dfs(i,a[i].l,0);
    65         ans=(ans*sum)%MOD;
    66         for (register int j=a[i].l;j<=a[i].r;j++)
    67         {
    68             register int q=find(e[j].x),p=find(e[j].y);
    69             if (p!=q)fa[q]=p;
    70         }
    71     }
    72     printf("%d
    ",ans);
    73 }
    View Code
  • 相关阅读:
    动态内存
    用c的数组简单的模拟了入栈
    c++实验,需要的人都知道是啥
    c语言的一个简单的链表
    c++的引用
    c++的一个有趣的程序
    奥运五环的绘制
    网页中的事件与事件响应
    响应事件的示例
    关于window.onload,window.onbeforeload与window.onunload
  • 原文地址:https://www.cnblogs.com/mczhuang/p/7695547.html
Copyright © 2020-2023  润新知