1 条题解

  • 0
    @ 2026-6-14 15:11:12

    // 最小生成树 Kruskal 算法 O(MlogM)
    #include<bits/stdc++.h>
    using namespace std;
    
    const int N=1e5+5,mod=1e9+7;
    int n,m,fa[N];
    struct E{int x,y,w;}e[N];
    long long sum,cnt=1;
    
    int find(int x){
      return fa[x]==x?x:fa[x]=find(fa[x]);
    }
    void merge(int x,int y){
      fa[find(x)]=find(y);
    }
    signed main(){
      scanf("%d%d",&n,&m);
      for(int i=1;i<=m;i++)scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].w);
      
      for(int i=1;i<=n;i++)fa[i]=i;
      sort(e+1,e+m+1,[&](E a,E b){return a.w<b.w;});
      
      for(int i=1,j,s1,s2; i<=m;){
        set<pair<int,int> >s;
        j=i,s1=0,s2=0;
        while(j<=m && e[i].w==e[j].w){ //如果边权相同
          int x=find(e[j].x),y=find(e[j].y); 
          if(x>y) swap(x,y); //保证起点小,终点大
          if(x!=y){ //不在一个集合
            s1++;  //累计边权相同的边数
            s.insert({x,y}); //set去重
          }
          j++; //快指针j右移
        }
        while(i<j){
          if(find(e[i].x)!=find(e[i].y)){
            merge(e[i].x,e[i].y); //加入生成树
            s2++; //累计可以加入生成树的边数
          }
          i++; //慢指针i右移
        }
        
        (sum+=e[i-1].w*s2)%=mod; //累加最小生成树的边权
        if(s1==2&&s2==1) cnt=(cnt*2)%mod;
        if(s1==3){
          if(s2==1) cnt=(cnt*3)%mod;
          if(s2==2) cnt=(cnt*s.size())%mod;
        } //累乘最小生成树的方案数
      }
      printf("%d %d\n",sum,cnt);
    }
    
    • 1

    D144 最小生成树 Kruskal 算法[USACO11DEC] Simplifying the Farm G

    信息

    ID
    2105
    时间
    1000ms
    内存
    128MiB
    难度
    10
    标签
    递交数
    2
    已通过
    2
    上传者