hdu 5723 Abandoned country(2016多校第一场) (最小生成树+期望)

Abandoned country

Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 1756    Accepted Submission(s): 475

 

Problem Description
An abandoned country has n(n100000) villages which are numbered from 1 to n. Since abandoned for a long time, the roads need to be re-built. There are m(m1000000) roads to be re-built, the length of each road is wi(wi1000000). Guaranteed that any two wi are different. The roads made all the villages connected directly or indirectly before destroyed. Every road will cost the same value of its length to rebuild. The king wants to use the minimum cost to make all the villages connected with each other directly or indirectly. After the roads are re-built, the king asks a men as messenger. The king will select any two different points as starting point or the destination with the same probability. Now the king asks you to tell him the minimum cost and the minimum expectations length the messenger will walk.
 

 

Input
The first line contains an integer T(T10) which indicates the number of test cases.

For each test case, the first line contains two integers n,m indicate the number of villages and the number of roads to be re-built. Next m lines, each line have three number i,j,wi, the length of a road connecting the village i and the village j is wi.
 

 

Output
output the minimum cost and minimum Expectations with two decimal places. They separated by a space.
 

 

Sample Input
1
4 6
1 2 1
2 3 2
3 4 3
4 1 4
1 3 5
2 4 6
 

 

Sample Output
6 3.33
 
 
Author
HIT
 
Source
 
Recommend
wange2014   |   We have carefully selected several similar problems for you:  5733 5732 5731 5730 5729 
 
这题我完全没有思路,比赛时也不会写,看了别人的代码,貌似懂了一点点。。
 
题意:给了一个图,求最小生成树和期望值,最小生成树指所有的点连接成一条完整的路的最小权值和,期望指图中任意两个点的距离之和除以所有的边的个数(如测试数据:4个点,就是用1-2,1-3,1-4,2-3,2-4,3-4这六条距离的和除以边长总数6)。
 
附上代码:
 
  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <algorithm>
  5 #define M 200010
  6 #define ll long long
  7 using namespace std;
  8 ll n,m;
  9 
 10 struct edge
 11 {
 12     int u,v;
 13     int w;
 14 } e[M*5];
 15 
 16 struct node
 17 {
 18     int u,v,w;
 19     int ans;   ///ans记录经过这条边能达到的边的个数
 20     int next;  ///next记录上一次连接的边的序号
 21 }ee[M];
 22 
 23 int father[M],head[M];  ///father数组表示根节点,head记录每条边最后一次连接的边的序号
 24 ll ans,sum;
 25 int tol;
 26 
 27 ll dfs(int u,int p)  ///搜索
 28 {
 29     ll num=0;
 30     for(int i=head[u];i!=-1;i=ee[i].next)
 31     {
 32         if(ee[i].v!=p)
 33         {
 34             ee[i].ans+=dfs(ee[i].v,ee[i].u);
 35             sum+=ee[i].ans*(n-ee[i].ans)*ee[i].w;  ///此边能到达的边的个数*能到此边的边的个数*边的长度
 36           //  cout<<ee[i].ans<<" "<<n-ee[i].ans<<" "<<ee[i].w<<endl;
 37             //cout<<sum<<endl;
 38             num+=ee[i].ans;
 39         }
 40     }
 41     return num;
 42 }
 43 
 44 void add_node(edge a)   ///建立邻接表
 45 {
 46     ee[tol].u=a.u;    ///正向
 47     ee[tol].v=a.v;
 48     ee[tol].w=a.w;
 49     ee[tol].ans=1;
 50     ee[tol].next=head[a.u];
 51     head[a.u]=tol++;
 52     ee[tol].u=a.v;    ///反向
 53     ee[tol].v=a.u;
 54     ee[tol].w=a.w;
 55     ee[tol].ans=1;
 56     ee[tol].next=head[a.v];
 57     head[a.v]=tol++;
 58 }
 59 
 60 int find(int x)   ///搜索根节点
 61 {
 62     while(x!=father[x])
 63         x=father[x];
 64     return x;
 65 }
 66 
 67 void sourch(int x,int y,int z,edge ss)
 68 {
 69     x=find(x);
 70     y=find(y);
 71     if(x!=y)   ///若根节点不相同
 72     {
 73         add_node(ss); ///并且此边存在,建立邻接表
 74         father[x]=y;  ///将其连接在一起
 75         ans+=z;
 76     }
 77 
 78 }
 79 
 80 void init()
 81 {
 82     ans=0,sum=0;
 83     int i,j;
 84     for(i=1; i<=n; i++)
 85     {
 86         father[i]=i;    ///将所有父节点初始定义为自己本身
 87         head[i]=-1;
 88     }
 89     tol=0;
 90     for(i=0; i<m; i++)
 91     {
 92         sourch(e[i].u,e[i].v,e[i].w,e[i]);  ///求最小生成树
 93     }
 94     dfs(1,-1);
 95     ll nn=n*(n-1)/2;
 96     printf("%I64d %.2lf
",ans,(double)sum/nn);
 97 }
 98 
 99 bool cmp(edge a,edge b)
100 {
101     return a.w<b.w;
102 }
103 
104 int main()
105 {
106     int T,i;
107     scanf("%d",&T);
108     while(T--)
109     {
110         scanf("%lld%lld",&n,&m);
111         for(i=0; i<m; i++)
112         {
113             scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w); ///记录每边的数据
114         }
115         sort(e,e+m,cmp);  ///要选取最小的花费,因此要进行排序
116         init();
117     }
118     return 0;
119 }
原文地址:https://www.cnblogs.com/pshw/p/5688809.html