zoukankan      html  css  js  c++  java
  • 1016: [JSOI2008]最小生成树计数

    Time Limit: 1 Sec  Memory Limit: 162 MB
    Submit: 7265  Solved: 3003
    [Submit][Status][Discuss]

    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
     
    首先要知道一个最小生成树性质:
      对于一个最小生成树中边权相等的边,如果替换后不影响连通情况,则这就是一个新的最小生成树。
    也就是说,对于一个最小生成树,边权相等的边的数量是固定的,因此我们只需要枚举这些边,再利用乘法原理,得出答案
      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 using namespace std;
      6 
      7 const int mod=31011;
      8 
      9 struct Edge
     10 {
     11     int u,v,w;
     12 }E[2000];
     13 
     14 struct Line
     15 {
     16     int l,r,v;
     17 }L[2000];
     18 int node;
     19 
     20 int n,m,tot,sum,ans=1;
     21 int F[10000];
     22 
     23 bool cmp(Edge A,Edge B)
     24 {
     25     return A.w<B.w;
     26 }
     27 
     28 int find(int x)
     29 {
     30     while(F[x]!=x) x=F[x];
     31     return x;
     32 }
     33 
     34 void dfs(int x,int now,int k)
     35 {
     36     if(now==L[x].r+1)
     37     {
     38         if(k==L[x].v) sum++;
     39         return;
     40     }
     41     int u=find(E[now].u);
     42     int v=find(E[now].v);
     43     if(u!=v)
     44     {
     45         F[u]=v;
     46         dfs(x,now+1,k+1);
     47         F[u]=u;F[v]=v;
     48     }
     49     dfs(x,now+1,k);
     50 }
     51 
     52 int main()
     53 {
     54     scanf("%d %d",&n,&m);
     55     for(int i=1;i<=n;i++) F[i]=i;
     56     for(int i=1;i<=m;i++)
     57     {
     58         int u,v,w;
     59         scanf("%d %d %d",&u,&v,&w);
     60         E[i]=(Edge){u,v,w};
     61     }
     62     sort(E+1,E+m+1,cmp);
     63     for(int i=1;i<=m;i++)
     64     {
     65         if(E[i].w!=E[i-1].w)
     66         {
     67             L[node].r=i-1;
     68             L[++node].l=i;
     69         }
     70         int u=find(E[i].u);
     71         int v=find(E[i].v);
     72         if(u!=v)
     73         {
     74             F[u]=v;
     75             L[node].v++;
     76             tot++;
     77         }
     78     }
     79     L[node].r=m;
     80     if(tot!=n-1)
     81     {
     82         printf("0");
     83         return 0;
     84     }
     85     for(int i=1;i<=n;i++) F[i]=i;
     86     for(int i=1;i<=node;i++)
     87     {
     88         sum=0;
     89         dfs(i,L[i].l,0);
     90         ans=(ans*sum)%mod;
     91         for(int j=L[i].l;j<=L[i].r;j++)
     92         {
     93             int u=find(E[j].u);
     94             int v=find(E[j].v);
     95             if(u!=v) F[u]=v;
     96         }
     97     }
     98     printf("%d
    ",ans);
     99     return 0;
    100 }
  • 相关阅读:
    [CodeForces]Codeforces Round #429 (Div. 2) ABC(待补)
    About Me
    2018-06-14
    Codeforces Codeforces Round #484 (Div. 2) E. Billiard
    Codeforces Codeforces Round #484 (Div. 2) D. Shark
    Codeforces Educational Codeforces Round 44 (Rated for Div. 2) F. Isomorphic Strings
    Codeforces Educational Codeforces Round 44 (Rated for Div. 2) E. Pencils and Boxes
    Codeforces Avito Code Challenge 2018 D. Bookshelves
    Codeforces Round #485 (Div. 2) D. Fair
    Codeforces Round #485 (Div. 2) F. AND Graph
  • 原文地址:https://www.cnblogs.com/InWILL/p/9451722.html
Copyright © 2011-2022 走看看