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

    OJ题号:
      BZOJ1016

    题目大意:
      给定一个无向带权图,求最小生成树的个数。

    思路:
      先跑一遍最小生成树,统计相同权值的边出现的个数。
      易证不同的最小生成树,它们不同的那一部分边的权值实际上是相同的。
      所以我们可以暴力枚举相同权值的边,统计加入这些边总共能有多少种方法。
      根据乘法原理,把每种边的方法数乘起来即可。
      然后就O(2^n)暴力水过这道题。
      实际上用Matrix-Tree可以做到O(n^3)。

      1 */
      2 #include<cstdio>
      3 #include<cctype>
      4 #include<vector>
      5 #include<algorithm>
      6 
      7 inline int getint() {
      8     register char ch;
      9     while(!isdigit(ch=getchar()));
     10     register int x=ch^'0';
     11     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
     12     return x;
     13 }
     14 const int mod=31011;
     15 const int V=101;
     16 
     17 struct Edge1 {
     18     int u,v,w;
     19     bool operator < (const Edge1 &another) const {
     20         return w<another.w;
     21     }
     22 };
     23 std::vector<Edge1> e1;
     24 
     25 struct Edge {
     26     int to,w;
     27 };
     28 std::vector<Edge> e[V];
     29 inline void add_edge(const int &u,const int &v,const int &w) {
     30     e[u].push_back((Edge){v,w});
     31 }
     32 
     33 struct DisjointSet {
     34     int anc[V],cnt;
     35     int find(const int &x) const {
     36         return x==anc[x]?x:find(anc[x]);
     37     }
     38     void reset(const int &n) {
     39         cnt=n;
     40         for(register int i=1;i<=n;i++) {
     41             anc[i]=i;
     42         }
     43     }
     44     void Union(const int &x,const int &y) {
     45         anc[find(x)]=find(y);
     46         cnt--;
     47     }
     48     bool isConnected(const int &x,const int &y) const {
     49         return find(x)==find(y);
     50     }
     51     int stat() const {
     52         return cnt;
     53     }
     54 };
     55 DisjointSet s;
     56 
     57 struct Hash {
     58     unsigned l,r;
     59     int v;
     60 };
     61 std::vector<Hash> a;
     62 
     63 inline void kruskal() {
     64     std::sort(e1.begin(),e1.end());
     65     for(register unsigned i=0;i<e1.size();i++) {
     66         if(!i) {
     67             a.push_back((Hash){0,0,0});
     68         } else if(e1[i].w!=e1[i-1].w) {
     69             a.back().r=i-1;
     70             a.push_back((Hash){i,0,0});
     71         }
     72         const int &u=e1[i].u,&v=e1[i].v,&w=e1[i].w;
     73         if(s.isConnected(u,v)) continue;
     74         s.Union(u,v);
     75         add_edge(u,v,w);
     76         add_edge(v,u,w);
     77         a.back().v++;
     78     }
     79     a.back().r=e1.size()-1;
     80 }
     81 
     82 int tmp;
     83 void dfs(const int &in,const unsigned x,const int d) {
     84     if(x>a[in].r) {
     85         if(d==a[in].v) tmp++;
     86         return;
     87     }
     88     const int &u=e1[x].u,&v=e1[x].v;
     89     const int p=s.find(u),q=s.find(v);
     90     if(p!=q) {
     91         s.anc[p]=q;
     92         dfs(in,x+1,d+1);
     93         s.anc[p]=p;
     94         s.anc[q]=q;
     95     }
     96     dfs(in,x+1,d);
     97 }
     98 
     99 int main() {
    100     int n=getint();
    101     for(register int m=getint();m;m--) {
    102         const int u=getint(),v=getint(),w=getint();
    103         e1.push_back((Edge1){u,v,w});
    104     }
    105     s.reset(n);
    106     kruskal();
    107     if(s.stat()!=1) {
    108         puts("0");
    109         return 0;
    110     }
    111     s.reset(n);
    112     int ans=1;
    113     for(register unsigned i=0;i<a.size();i++) {
    114         tmp=0;
    115         dfs(i,a[i].l,0);
    116         ans=(ans*tmp)%mod;
    117         for(register unsigned j=a[i].l;j<=a[i].r;j++) {
    118             const int &u=e1[j].u,&v=e1[j].v;
    119             if(s.isConnected(u,v)) continue;
    120             s.Union(u,v);
    121         }
    122     }
    123     printf("%d
    ",ans);
    124     return 0;
    125 }
  • 相关阅读:
    mybatis使用*号查询数据丢失问题
    设计四个线程,其中两个线程每次对j增加1,另外两个线程对j每次减1,写出程序
    用代码实现以下程序:篮子中有10个玩具,每60秒取出3个,同时每40秒向篮子中放入1个,不断重复上述动作,当篮子中剩余玩具不足3个是,程序结束
    伽马分布的性质
    三角函数公式
    微分和积分的中值定理
    一些需要理解掌握的知识点
    一阶微分不变性
    泰勒展开和麦克劳林级数
    重要极限(1+1/n)的n次方
  • 原文地址:https://www.cnblogs.com/skylee03/p/7575427.html
Copyright © 2011-2022 走看看