BZOJ 3754 Tree之最小方差树 MST
Description
Wayne 在玩儿一个很有趣的游戏。在游戏中,Wayne 建造了N 个城市,现在他想在这些城市间修一些公路,当然并不是任意两个城市间都能修,为了道路系统的美观,一共只有M 对城市间能修公路,即有若干三元组(Ui, Vi,Ci) 表示Ui 和Vi 间有一条长度为Ci 的双向道路。当然,游戏保证了,若所有道路都修建,那么任意两城市可以互相到达。
Wayne 拥有恰好N - 1 支修建队,每支队伍能且仅能修一条道路。当然,修建长度越大,修建的劳累度也越高,游戏设定是修建长度为C 的公路就会有C 的劳累度。当所有的队伍完工后,整个城市群必须连通,而这些修建队伍们会看看其他队伍的劳累情况,若劳累情况差异过大,可能就会引发骚动,不利于社会和谐发展。Wayne 对这个问题非常头疼,于是他想知道,这N - 1 支队伍劳累度的标准差最小能有多少。
标准差的定义:设有n的数ai,它们的平均数是a¯,那么标准差就是:∑n−1i=0(ai−a¯)2n−−−−−−−−−−−−√
注意:【BZOJ3754】并没有这道题。
Data Constraint
对于20% 的数据,M <= 20。
对于另外30% 的数据,Ci<= 10。
对于100% 的数据,N <= 100,M <= 2000,Ci <= 100。
Solution
对于20%数据,枚举每个选不选即可。
然后我们看无论是30%的还是100%的数据,它们的Ci都比较小。假设平均数为a¯,
那么答案就是:
这个式子最小,发现就是求方差最小,发现数据很小,发现可以枚举平均值来解决,就是最大的平均值,和最小的平均值,
之间枚举就可以了。
1 #include<cmath> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #define N 105 6 #define M 2010 7 #define sqr(x) ((x)*(x)) 8 using namespace std; 9 int n,m,tot,f[N];double ans=1e9; 10 int find(int x){return f[x]==x?x:f[x]=find(f[x]);} 11 struct edge{int x,y,c;double w;}e[M]; 12 inline bool operator<(edge x,edge y){return x.w<y.w;} 13 double solve() 14 { 15 for(int i=1;i<=n;i++)f[i]=i; 16 int tot=0;double sum=0; 17 for(int i=1;tot!=n-1;i++) 18 { 19 int fx=find(e[i].x),fy=find(e[i].y); 20 if(fx==fy)continue; 21 tot++; 22 f[fx]=fy; 23 sum+=e[i].w; 24 } 25 return sum; 26 } 27 int main() 28 { 29 scanf("%d%d",&n,&m); 30 for(int i=1;i<=m;i++) 31 scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].c),e[i].w=e[i].c; 32 int Min,Max; 33 sort(e+1,e+m+1); 34 Min=solve(); 35 reverse(e+1,e+m+1); 36 Max=solve(); 37 for(int i=Min;i<=Max;i++) 38 { 39 double ave=i*1.0/(n-1); 40 for(int j=1;j<=m;j++) 41 e[j].w=sqr(e[j].c-ave); 42 sort(e+1,e+m+1); 43 ans=min(ans,solve()); 44 } 45 printf("%.4lf\n",sqrt(ans/(n-1))); 46 }