• BZOJ 1016 最小生成树计数


    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,000。数据保证不会出现自回边和重边。注意:具有相同权值的边不会超过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

     这题要猜一个结论——长为i的边个数是一定的以及前i小的边他们构成的并查集是一定的,这样就可以 2^n dfs了(相同长度的边<=10)。

     
     1 #include<algorithm>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<cstdlib>
     5 using namespace std;
     6 
     7 #define maxn (110)
     8 #define maxm (1010)
     9 #define rhl (31011)
    10 
    11 int father[maxn],save[maxn],bac[maxm],road[maxm];
    12 int n,m,tot,ans,sum;
    13 struct E{ int u,v,w; }edge[maxm];
    14 
    15 inline void init() {for (int i = 1;i <= n;++i) father[i] = i;}
    16 
    17 inline int find(int a) {if (father[a] != a) father[a] = find(father[a]); return father[a];} 
    18 
    19 inline bool cmp(E a,E b){ return a.w < b.w; }
    20 
    21 inline void mst()
    22 {
    23     sort(edge+1,edge+m+1,cmp); init();
    24     int have = 0,r1,r2,pos;
    25     for (int i = 1;i <= m;++i)
    26     {
    27         r1 = find(edge[i].u),r2 = find(edge[i].v);
    28         if (r1 != r2)
    29         {
    30             father[r1] = r2; ++have;
    31             pos = lower_bound(bac+1,bac+tot+1,edge[i].w)-bac;
    32             ++road[pos];
    33         }
    34         if (have == n - 1) break;
    35     }
    36     if (have < n - 1) printf("0"),exit(0);
    37 }
    38 
    39 inline void dfs(int a,int r,int pos,int cho)
    40 {
    41     if (road[pos] == cho)
    42     {
    43         ++sum;
    44         if (sum == 1) memcpy(save,father,sizeof(save));
    45         return;
    46     }
    47     if (a > r) return;
    48     if (cho+r-a+1<road[pos]) return;
    49     int temp[maxn];
    50     dfs(a+1,r,pos,cho);
    51     memcpy(temp,father,sizeof(temp));
    52     int r1 = find(edge[a].u),r2 = find(edge[a].v);
    53     if (r1 != r2) father[r1] = r2,dfs(a+1,r,pos,cho+1);
    54     memcpy(father,temp,sizeof(temp));
    55 }
    56 
    57 int main()
    58 {
    59     freopen("1016.in","r",stdin);
    60     freopen("1016.out","w",stdout);
    61     scanf("%d %d",&n,&m);
    62     for (int i = 1;i <= m;++i)
    63     {
    64         int a,b,c;
    65         scanf("%d %d %d",&a,&b,&c);
    66         edge[i] = (E) {a,b,c};
    67         bac[i] = c;
    68     }
    69     sort(bac+1,bac+m+1);
    70     tot = unique(bac+1,bac+m+1)-bac-1;
    71     mst();
    72     init(); ans = 1;
    73     for (int i = 1;i <= m;)
    74     {
    75         int j = i;
    76         while (j < m && edge[j+1].w == edge[i].w) ++j;
    77         sum = 0;
    78         dfs(i,j,lower_bound(bac+1,bac+tot,edge[i].w)-bac,0);
    79         (ans *= sum)%=rhl;
    80         memcpy(father,save,sizeof(save));
    81         i = j+1;
    82     }
    83     printf("%d",ans);
    84     fclose(stdin); fclose(stdout);
    85     return 0;
    86 }
    View Code
  • 相关阅读:
    RabbitMQ与AMQP协议详解
    MemCache超详细解读
    ASP.NET Web API通过ActionFilter来实现缓存
    ASP.NET Web API 通过Authentication特性来实现身份认证
    什么是CSR证书申请文件?
    跨平台的 SQL 客户端
    Java生成公私钥对
    git 删除错误提交的commit
    ServiceStack.Text反序列化lowercase_underscore_names格式的JSON
    .NET AES加解密(128位)
  • 原文地址:https://www.cnblogs.com/mmlz/p/4266175.html
Copyright © 2020-2023  润新知