题目需要我们求把所有城市连起来用到的最小路程,和选择任意两点的路程和除以总对点数就是期望了
所以我们要用最小生成树求最小路程,再遍历找每一条边的子节点个数,用公式(子节点的个数)*(总节点数-子节点数)就是该边在期望中贡献的次数,再乘边长就行了。
Abandoned country
Time Limit : 8000/4000ms (Java/Other) Memory Limit : 65536/65536K (Java/Other)
Total Submission(s) : 93 Accepted Submission(s) : 24
Font: Times New Roman | Verdana | Georgia
Font Size: ← →
Problem Description
Input
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
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
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<string>
#include<vector>
#include<queue>
#include<map>
#include<set>
#define INF 999999999
#define LL long long
#define mod 1000003
#define maxn 1000005
using namespace std;
int p[100005];
int n, m;
struct Edge
{
int from, to;
LL dist;
Edge() {}
Edge(int u, int v, LL d) :from(u), to(v), dist(d) {};
};
vector<Edge> edges;
vector<int> G[100005];
int mm;
struct node
{
int u, v;
LL w;
};
node poi[1000005];
void AddEdge(int from, int to, LL dist)
{
edges.push_back(Edge(from, to, dist));
G[from].push_back(mm++);
}
int cmp(node a, node b)
{
return a.w<b.w;
}
int find(int x)//并查集+路径压缩
{
int r = x;
while (p[r] != r)
r = p[r];
int i = x, j;
while (i != r)
{
j = p[i];
p[i] = r;
i = j;
}
return r;
}
LL kru()//运用紫书的方法竟然超时,最后学了大神的方法
{
LL ans = 0;
int cnt = 0;
for (int i = 0; i <= n; i++) p[i] = i;
sort(poi, poi + m, cmp);
for (int i = 0; i<m; i++)
{
int x = find(poi[i].u);
int y = find(poi[i].v);
if (x != y)
{
AddEdge(poi[i].u, poi[i].v, poi[i].w);
AddEdge(poi[i].v, poi[i].u, poi[i].w);
ans += poi[i].w;
p[x] = y;
if (++cnt >= n - 1)
break;
}
}
return ans;
}
int siz[100005];
double dasiz[100005];
void dfs(int root, int fa)//深搜递归每个节点
{
siz[root] = 1;
for (int i = 0; i <G[root].size(); i++)
{
Edge &ee = edges[G[root][i]];
LL len = ee.dist;
int son = ee.to;
if (son == fa)
continue;
dfs(son, root);
siz[root] += siz[son];
dasiz[root] += dasiz[son] + (LL)siz[son] * (LL)(n - siz[son])*(double)len;
}
}
int main()
{
int t;
scanf("%d", &t);
while (t--)
{
mm = 0;
int ff = 0;
scanf("%d%d", &n, &m);
if (m == 0)
ff = 1;
for (int i = 0; i<m; i++)
{
scanf("%d %d %I64d", &poi[i].u, &poi[i].v, &poi[i].w);
}
LL sum = kru();
memset(siz, 0, sizeof(siz));
memset(dasiz, 0, sizeof(dasiz));
dfs(1, -1);
LL tti = (LL)(n - 1)*(LL)n;//n是整型,必须转化为LL,要不会爆int
LL ti = tti / 2;
printf("%I64d", sum);
if (ff == 0)
printf(" %.2lf\n", (double)dasiz[1] / ti);
else
printf(" 0.00\n");
for (int i = 0; i <= n; i++)
{
G[i].clear();
}
edges.clear();
}
}