官方题解: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 }
View Code

相关文章: