1 条题解
-
0

// 最小生成树 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
信息
- ID
- 2105
- 时间
- 1000ms
- 内存
- 128MiB
- 难度
- 10
- 标签
- 递交数
- 2
- 已通过
- 2
- 上传者