bzoj1016/luogu4208 最小生成树计数 (kruskal+暴搜)
由于有相同权值的边不超过10条的限制,所以可以暴搜
先做一遍kruskal,记录下来每个权值的边使用的数量(可以离散化一下)
可以证明,对于每个权值,所有的最小生成树中选择的数量是一样的、而且它们连成的连通块也是一样的
所以我们把每个权值的边分开暴搜所有可能的情况,最后再乘到一起就是答案
1 #include<bits/stdc++.h> 2 #define pa pair<int,int> 3 #define CLR(a,x) memset(a,x,sizeof(a)) 4 using namespace std; 5 typedef long long ll; 6 const int maxn=110,maxm=1010,P=31011; 7 8 inline ll rd(){ 9 ll x=0;char c=getchar();int neg=1; 10 while(c<'0'||c>'9'){if(c=='-') neg=-1;c=getchar();} 11 while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar(); 12 return x*neg; 13 } 14 15 struct Edge{ 16 int a,b; 17 ll l; 18 }eg[maxm]; 19 int egh[maxn],ect; 20 int N,M,L,cnt[maxm]; 21 int fa[maxn],ans,sum; 22 23 inline bool cmp(Edge a,Edge b){return a.l<b.l;} 24 inline int getf(int x){ 25 while(x!=fa[x]) x=fa[x];return x; 26 } 27 28 void dfs(int x,int y,int n){ 29 if(x>M||eg[x].l!=y){ 30 if(n==cnt[y]) sum=(sum+1)%P; 31 return; 32 } 33 int aa=getf(eg[x].a),bb=getf(eg[x].b); 34 if(aa!=bb){ 35 fa[aa]=bb; 36 dfs(x+1,y,n+1); 37 fa[aa]=aa; 38 } 39 dfs(x+1,y,n); 40 } 41 42 int main(){ 43 //freopen("","r",stdin); 44 int i,j,k; 45 N=rd(),M=rd(); 46 for(i=1;i<=M;i++){ 47 eg[i].a=rd(),eg[i].b=rd(); 48 eg[i].l=rd(); 49 }sort(eg+1,eg+M+1,cmp); 50 int lst=-1; 51 for(i=1,j=0;i<=M;i++){ 52 if(eg[i].l!=lst) j++; 53 lst=eg[i].l,eg[i].l=j; 54 } 55 for(i=1;i<=N;i++) fa[i]=i; 56 for(i=1,j=0;i<=M;i++){ 57 int x=getf(eg[i].a),y=getf(eg[i].b); 58 if(x!=y){ 59 fa[x]=y; 60 j++;cnt[eg[i].l]++; 61 } 62 } 63 if(j<N-1){printf("0\n");return 0;} 64 for(i=1;i<=N;i++) fa[i]=i; 65 int ans=1; 66 for(i=1,j=0;i<=M;i++){ 67 if(eg[i].l!=eg[i-1].l){ 68 sum=0;dfs(i,eg[i].l,0); 69 ans=(ans*sum)%P; 70 } 71 int x=getf(eg[i].a),y=getf(eg[i].b); 72 if(x!=y){ 73 fa[x]=y;j++; 74 } 75 } 76 printf("%d\n",ans); 77 return 0; 78 }