传送门
【题目分析】
先说说自己在考场上YY出来的错误解法,但可以过后面几个数据密度大的点。
将所有边按权值存入各自的vector中,然后一个一个的枚举,因为要标准差最小所以边权要尽可能的集中所以记录两个指针,优先跳差值小的一边。
因为到最后边数上万,但边权小于等于100,所以可能一个集合就差不多能将整个图覆盖,所以靠着这个方法过了最后6个点。
然而这个很容易找反例,所以咕了。
观察标准差求解公式:,因为边权是整数,所以可以考虑直接枚举平均数,以0.25为界即可。
可以将上面的公式化简一下得到,根据这个式子计算最后的结果。
【代码~】
#include<bits/stdc++.h>
using namespace std;
const int MAXN=1e2+10;
const int MAXM=2e3+10;
int n,m;
int fa[MAXN];
int ans=0x3f3f3f3f;
int sum1,sum2;
struct Edge{
int u,v,w;
double fc;
friend inline bool operator<(const Edge &a,const Edge &b){
return a.fc<b.fc;
}
}edge[MAXM];
int Read(){
int i=0,f=1;
char c;
for(c=getchar();(c>'9'||c<'0')&&c!='-';c=getchar());
if(c=='-')
f=-1,c=getchar();
for(;c>='0'&&c<='9';c=getchar())
i=(i<<3)+(i<<1)+c-'0';
return i*f;
}
int find(int x){
if(x==fa[x])
return x;
return fa[x]=find(fa[x]);
}
int main(){
n=Read(),m=Read();
for(int i=1;i<=m;++i)
edge[i].u=Read(),edge[i].v=Read(),edge[i].w=Read();
for(double aver=0.0;aver<=100.0;aver+=0.25){
sum1=sum2=0;
for(int i=1;i<=n;++i)
fa[i]=i;
for(int i=1;i<=m;++i)
edge[i].fc=(edge[i].w-aver)*(edge[i].w-aver);
sort(edge+1,edge+m+1);
for(int i=1;i<=m;++i){
int u=edge[i].u,v=edge[i].v;
int fu=find(u),fv=find(v);
if(fu!=fv){
sum1+=edge[i].w,sum2+=edge[i].w*edge[i].w;
fa[fv]=fu;
}
}
ans=min(ans,(n-1)*sum2-sum1*sum1);
}
printf("%.4lf",sqrt(ans)/(n-1));
return 0;
}