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


    题解:

    最小生成树的两个性质:

    1、边权相等的边的个数一定。

    2、做完边权为w的所有边时,图的连通性相同。

    然后就暴力dfs吧~

    View Code
      1 #include <cstdio>
      2 #include <iostream>
      3 #include <algorithm>
      4 #include <cstdlib>
      5 #include <cstring>
      6  
      7 #define N 2000
      8 #define M 30000
      9 #define mod 31011
     10  
     11 using namespace std;
     12  
     13 struct KRU
     14 {
     15     int a,b,d;
     16 }kru[M];
     17  
     18 int n,m,fa[N],f2[N],st[M],sum[M],cnt,ans=1,tans;
     19 bool vis[N];
     20  
     21  
     22 inline bool cmp(const KRU &a,const KRU &b)
     23 {
     24     return a.d<b.d;
     25 }
     26  
     27 void read()
     28 {
     29     scanf("%d%d",&n,&m);
     30     for(int i=1;i<=m;i++) scanf("%d%d%d",&kru[i].a,&kru[i].b,&kru[i].d);
     31     sort(kru+1,kru+1+m,cmp);
     32 }
     33  
     34 int findfa(int x)
     35 {
     36     if(x!=fa[x]) fa[x]=findfa(fa[x]);
     37     return fa[x];
     38 }
     39  
     40 int findpa(int x)
     41 {
     42     if(x!=f2[x]) return findpa(f2[x]);
     43     return x;
     44 }
     45  
     46 void dfs(int l,int r,int num)
     47 {
     48     if(num==0) {tans++;return;}
     49     if(l>r) return;
     50     int fx=findpa(kru[l].a),fy=findpa(kru[l].b);
     51     if(vis[kru[l].a]&&vis[kru[l].b]&&fx!=fy)
     52     {
     53         f2[fx]=fy;
     54         dfs(l+1,r,num-1);
     55         f2[fx]=fx;
     56     }
     57     dfs(l+1,r,num);
     58 }
     59  
     60 void work(int x)
     61 {
     62     tans=0;
     63     dfs(st[x],st[x+1]-1,sum[x]);
     64     ans=(ans*tans)%mod;
     65 }
     66  
     67 void kruskal()
     68 {
     69     memset(vis,0,sizeof vis);
     70     for(int i=1;i<=n;i++) fa[i]=f2[i]=i;
     71     int num=1,i;
     72     cnt=0;
     73     for(i=1;i<=m;i++)
     74     {
     75         if(i==1||kru[i].d!=kru[i-1].d)
     76         {
     77             st[++cnt]=i; sum[cnt]=0;
     78             if(i!=1) work(cnt-1);
     79             for(int j=1;j<=n;j++) f2[j]=fa[j];
     80         }
     81         if(findfa(kru[i].a)!=findfa(kru[i].b))
     82         {
     83             num++; sum[cnt]++;
     84             fa[findfa(kru[i].a)]=findfa(kru[i].b);
     85             vis[kru[i].a]=vis[kru[i].b]=true;
     86         }
     87         if(num==n) break;
     88     }
     89     kru[m+1].d=-1;
     90     for(int j=i+1;j<=m+1;j++)
     91         if(kru[j-1].d!=kru[j].d)
     92         {
     93             st[cnt+1]=j;
     94             break;
     95         }
     96     work(cnt);
     97     if(num==n) printf("%d\n",ans);
     98     else printf("0\n");
     99 }
    100  
    101 int main()
    102 {
    103     read(),kruskal();
    104     return 0;
    105 } 
  • 相关阅读:
    allocation size overflow
    数据库隔离级别深入理解(ORACLE)
    查看Orcale数据里的表是否有变化
    意外发现抽象类的构造器
    C语言学习快速笔记
    由javascript的闭包引申到程序语言编译上的自由变量作用域的考量
    easyui的datagrid的列checkbox自定义增加disabled选项
    数据库连接不关闭造成的问题以及RowSet的使用
    Quartz的JobDetail没有触发器指向时会被删除的问题
    发现浏览器开发工具的一个小问题
  • 原文地址:https://www.cnblogs.com/proverbs/p/2945059.html
Copyright © 2020-2023  润新知