• bzoj1016 [JSOI2008]最小生成树计数


    先做一遍kruskal,然后发现不同的方案只可能是相同权值的不同的边干了相同的事

    题目又保证了相同权值的边数很少,直接状压即可

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <iostream>
     4 #include <algorithm>
     5 #include <cmath>
     6 #define N 1005
     7 using namespace std;
     8 int getnum(int x){
     9     int cnt=0;
    10     while(x){cnt+=x&1;x>>=1;}
    11     return cnt;
    12 }
    13 int n,m,ans=1;
    14 int fa[N],tmp[N];
    15 int find(int x,int *y){
    16     if(x==y[x])return x;
    17     return y[x]=find(y[x],y);
    18 }
    19 struct edge{int u,v,w;}ed[10*N];
    20 bool cmp(edge a,edge b){return a.w<b.w;}
    21 bool vis[10*N];
    22 int bit[15];
    23 int main(){
    24     bit[0]=1;
    25     for(int i=1;i<=10;i++)bit[i]=bit[i-1]<<1;
    26     scanf("%d%d",&n,&m);
    27     for(int i=1;i<=n;i++)fa[i]=i;
    28     for(int i=1;i<=m;i++)
    29         scanf("%d%d%d",&ed[i].u,&ed[i].v,&ed[i].w);
    30     sort(ed+1,ed+m+1,cmp);
    31     for(int i=1,fv,fu;i<=m;i++){
    32         fu=find(ed[i].u,fa);fv=find(ed[i].v,fa);
    33         if(fu!=fv){
    34             fa[fu]=fv;
    35             vis[i]=1;
    36         }
    37     }
    38     for(int be=1,en,num,len,cnt,flag;be<=m;be++){
    39         for(en=be;en<=m&&ed[en+1].w==ed[be].w;en++);
    40         for(int i=1;i<=n;i++)fa[i]=tmp[i]=i;
    41         num=n-1;cnt=0;
    42         for(int i=1;i<=m;i++){
    43             if(i>=be&&i<=en)continue;
    44             if(vis[i]){
    45                 int fu=find(ed[i].u,tmp),fv=find(ed[i].v,tmp);
    46                 tmp[fu]=fv;num--;
    47             }
    48         }
    49         len=en-be+1;
    50         for(int i=0;i<bit[len];i++)if(getnum(i)==num){
    51             flag=0;
    52             memcpy(fa,tmp,sizeof fa);
    53             for(int j=be;j<=en;j++){
    54                 if(i&bit[j-be]){
    55                     int fu=find(ed[j].u,fa),fv=find(ed[j].v,fa);
    56                     if(fu==fv){flag=1;break;}
    57                     fa[fu]=fv;
    58                 }
    59             }
    60             if(flag==0)cnt++;
    61         }
    62         ans=ans*cnt%31011;
    63         be=en;
    64     }
    65     printf("%d
    ",ans);
    66     return 0;
    67 }
    View Code
  • 相关阅读:
    HDU5343:MZL's Circle Zhou(SAM,记忆化搜索DP)
    动归皆背包——那些做过的背包
    CODEVS 3943 数学奇才琪露诺
    codevs 1540 银河英雄传说
    CODEVS 1004四子连棋
    洛谷1082 同余方程
    洛谷1006 传纸条
    洛谷1508 Likecloud-吃、吃、吃
    洛谷1108 低价购买
    洛谷1156 垃圾陷阱
  • 原文地址:https://www.cnblogs.com/Ren-Ivan/p/8184653.html
Copyright © 2020-2023  润新知