题解P2143 [JSOI2010] 巨额奖金

题意就是让你求有多少种最小生成树

生成树用 kruskal 求就好了

我们考虑用 dfs 中用乘法原理去计数

#include<bits/stdc++.h>
#define N 1000100
using namespace std;
typedef long long ll;
ll n,m,cnt[N],fa[N],ans=1,c[N];
const ll mod=31011;
struct edge{
    ll u,v,w;
}e[N];
inline ll fr(){
    register ll s=0,k=1;register char ch=getchar();
    while(!isdigit(ch)){if(ch=='-') k=-1;ch=getchar();};
    while(isdigit(ch)){s=(s<<3)+(s<<1)+ch-'0';ch=getchar();};
    return s*k;
}
inline bool cmp(const edge& x,const edge& y){
    return x.w<y.w;
}
inline ll find(ll x){
    return fa[x]==x?x:find(fa[x]);//由于我们合并后还要拆开,所以绝对不能路径压缩 
}
inline bool kruskal(){//kruskal最小生成树 
    ll tot=0;
    for(ll i=1;i<=n;i++) fa[i]=i;
    for(ll i=1;i<=m;i++){
        ll x=find(e[i].u),y=find(e[i].v);//查找 
        if(x!=y){
            tot++;
            cnt[e[i].w]++;
            fa[x]=y;
        }
        if(tot==n-1) return true;
    }
    return false;
}
inline ll dfs(ll now,ll w,ll s){
    if(s==cnt[w]) return 1ll;//如果等于了则算为一种方案 
    if(e[now].w!=w) return 0ll;
    ll sum=0,x=find(e[now].u),y=find(e[now].v);
    if(x!=y){
        fa[x]=y;//合并 
        sum=dfs(now+1,w,s+1);//把这个答案记进来 
        fa[x]=x,fa[y]=y;//在拆开,方便下面找边时继续合并 
    }
    return sum+dfs(now+1,w,s); //算出总的方案数 
}
int main(){
    scanf("%lld%lld",&n,&m);
    for(ll i=1;i<=m;i++){
        scanf("%lld%lld%lld",&e[i].u,&e[i].v,&e[i].w),c[i]=e[i].w;
    }
    sort(c+1,c+m+1);
    sort(e+1,e+m+1,cmp);
    ll len=unique(c+1,c+m+1)-c-1;
    for(ll i=1;i<=m;i++){
        e[i].w=lower_bound(c+1,c+len+1,e[i].w)-c;//离散化 
    }
    if(!kruskal()){
        puts("0");
        return 0;
    }
    for(ll i=1;i<=n;i++) fa[i]=i;
    for(ll i=1;i<=m;i++){
        if(e[i].w==e[i-1].w||!cnt[e[i].w]) continue;//相同的边我们一起处理,如果没有这个权值的边,同样continue 
        ans=ans*dfs(i,e[i].w,0ll)%mod;//计数,运用乘法原理 
        ll j=i;
        while(e[j].w==e[i].w){//只要相等,则合并 
            ll x=find(e[j].u),y=find(e[j].v);
            fa[x]=y;
            j++;//每次找新的权值相等的边 
        }
    }
    printf("%lld",ans%mod);
    return 0;
}

 

posted @ 2022-08-18 20:26  After_light  阅读(38)  评论(0)    收藏  举报