题目描述
输入格式
输出格式
输入输出样例
输入 #1
5 10
5 2 18903
1 2 74504
5 1 22377
1 4 55995
3 1 44838
4 1 19622
1 2 62132
1 5 59540
5 4 56342
5 3 27255
输出 #1
18903 1
93407 3
41280 3
97275 4
142113 5
105740 5
105740 5
105740 5
105740 5
88157 5
说明/提示
数据规模与约定
提示
解题思路
由于边数⽐较少,每次采取 Kruskal 算法,这个算法是可以求出最⼤的最⼩⽣成森林的。连
通块⼤⼩可以在并查集⾥顺便维护。
第⼆问的答案⼀定是唯⼀的,否则可以通过加⼀条边连通两个不同答案情况的连通块,也就是说这两个答案均不是最⼤的最⼩⽣成森林。
PS:注意到,读⼊⼀条新边时,之前的边集已经按照⻓度排好序,可以直接寻找到相应的位置插⼊,省去了每次排序的复杂度。
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<algorithm>
#include<queue>
using namespace std;
int n,m,ans,cnt,fa[6000],s[6000];
struct c{
int x,y,w;
}a[6000];
int find(int a)
{
if(fa[a]==a) return a;
else return fa[a]=find(fa[a]);
}
int main() {
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].w);
for(int j=i;j>0&&a[j].w<a[j-1].w;j--)
swap(a[j],a[j-1]);
int ans=0,cnt=0;
for(int j=1;j<=n;j++)
{
fa[j]=j;
s[j]=1;
}
for(int j=1;j<=i&&cnt<=n-1;j++)
{
int x=find(a[j].x);
int y=find(a[j].y);
if(x!=y)
{
ans+=a[j].w;
fa[x]=fa[y];
s[y]+=s[x];
++cnt;
}
}
printf("%d %d\n",ans,s[find(1)]);
}
}