官方题解:http://bestcoder.hdu.edu.cn/blog/2016-multi-university-training-contest-1-solutions-by-hit/
题目链接:
A http://acm.hdu.edu.cn/showproblem.php?pid=5723
第一步求最小生成树,因为题目限制边权各不相同,所以最小生成树唯一。第二步求任意树上任意两点距离的均值,通过计算每条边对总和的贡献得到。枚举每条边,经过次数等于该边左边点的个数乘右边点的个数。dfs求有根树每个点子树节点个数的办法。
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int M=1e6+10; 4 struct E { 5 int u,v; 6 double w; 7 } e[M]; 8 int n,m; 9 double cost; 10 double average; 11 struct G{ 12 struct E{ 13 int v,next; 14 double w; 15 }e[M]; 16 int le,head[M]; 17 void init(int n){ 18 le=0; 19 for(int i=0;i<=n;i++) head[i]=-1; 20 } 21 void add(int u,int v,double w){ 22 e[le].v=v; 23 e[le].w=w; 24 e[le].next=head[u]; 25 head[u]=le++; 26 } 27 }g; 28 class Kruskal { ///最小生成树(无向图) O(E*log(E)) 29 typedef double typec; ///边权的类型 30 static const int ME=1e6+10; ///边的个数 31 static const int MV=1e5+10; ///点的个数 32 class UnionFindSet { ///并查集 33 int par[MV]; 34 void add(int son,int fa) { 35 par[fa]+=par[son]; 36 par[son]=fa; 37 } 38 public: 39 void init(int n) { 40 for(int i=0; i<=n; i++) par[i]=-1; 41 } 42 int getroot(int x) { 43 int i=x,j=x,temp; 44 while(par[i]>=0) i=par[i]; 45 while(j!=i) { 46 temp=par[j]; 47 par[j]=i; 48 j=temp; 49 } 50 return i; 51 } 52 bool unite(int x,int y) { 53 int p=getroot(x); 54 int q=getroot(y); 55 if(p==q) return false; 56 if(par[p]>par[q]) { 57 add(p,q); 58 } 59 else { 60 add(q,p); 61 } 62 return true; 63 } 64 } ufs; 65 struct E { 66 int u,v; 67 typec w; 68 friend bool operator < (const E &a,const E &b) { 69 return a.w<b.w; 70 } 71 } e[ME]; 72 int le,num,n; 73 typec res; 74 public: 75 void init(int tn) { ///传入点的个数 76 n=tn; 77 le=0; 78 } 79 void add(int u,int v,typec w) { 80 e[le].u=u; 81 e[le].v=v; 82 e[le].w=w; 83 le++; 84 } 85 typec solve() { ///返回-1 不连通 86 res=0; 87 num=1; 88 ufs.init(n); 89 sort(e,e+le); 90 for(int i=0; i<le&&num<n; i++) { 91 if(ufs.unite(e[i].u,e[i].v)) { 92 num++; 93 res+=e[i].w; 94 g.add(e[i].u,e[i].v,e[i].w); 95 g.add(e[i].v,e[i].u,e[i].w); 96 } 97 } 98 if(num<n) res=-1; 99 return res; 100 } 101 } mst; 102 int dfs(int u,int fa){ 103 int sum=1; 104 for(int i=g.head[u];~i;i=g.e[i].next){ 105 int v=g.e[i].v; 106 if(v==fa) continue; 107 double w=g.e[i].w; 108 int son=dfs(v,u); 109 sum+=son; 110 average+=w*son*(n-son); 111 } 112 return sum; 113 } 114 void solve() { 115 g.init(n); 116 mst.init(n); 117 for(int i=0;i<m;i++){ 118 mst.add(e[i].u,e[i].v,e[i].w); 119 } 120 cost=mst.solve(); 121 average=0; 122 dfs(1,-1); 123 average*=2; 124 average/=n; 125 average/=(n-1); 126 } 127 int main() { 128 int t; 129 while(~scanf("%d",&t)) { 130 while(t--) { 131 scanf("%d%d",&n,&m); 132 for(int i=0; i<m; i++) { 133 scanf("%d%d%lf",&e[i].u,&e[i].v,&e[i].w); 134 } 135 solve(); 136 printf("%.0f %.2f\n",cost,average); 137 } 138 } 139 return 0; 140 }