题意要求跑最小生成树,然后求出任意两点距离的期望。
做法是用Kruskal算法并用前向星存最小生成树,然后用dfs得出期望。
代码
#include<bits/stdc++.h>
#include<vector>
using namespace std;
#define ll long long int
struct Edge{
int x;
int y;
int wei;
}num[1010000];
struct Node {
int to;
int val;
Node(int _to, int _val)
:to(_to), val(_val) {}
};
int vis[101000];
int sum[101000];
ll res;
int n,m,k;
vector<Node>vet[101000];
int init(int n)
{
for(int i=1;i<=n;i++)
{
vis[i]=i;
}
}
int finds(int x)
{
if(x!=vis[x])
{
vis[x]=finds(vis[x]);
}
return vis[x];
}
int cmp(Edge a,Edge b)
{
return a.wei<b.wei;
}
void Dfs(int root, int father) {
sum[root] = 1;
for(int i = 0; i < vet[root].size(); i++) {
int son = vet[root][i].to;
int val = vet[root][i].val;
if(son == father) continue;
Dfs(son, root);
sum[root] += sum[son];
res += (ll)(sum[son]) * (ll)(n - sum[son]) * val;
}
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d %d",&n,&m);
long long int cnt=0;
for(int i=1;i<=m;i++)
{
scanf("%d %d %d",&num[i].x,&num[i].y,&num[i].wei);
}
for(int i = 1; i <= n; i++) vet[i].clear();
sort(num,num+m,cmp);
init(n);
for(int i=1;i<=m;i++)
{
int u=num[i].x;
int v=num[i].y;
int fu=finds(u);
int fv=finds(v);
if(fu!=fv)
{
cnt+=num[i].wei;
vis[fu]=fv;
vet[num[i].x].push_back(Node(num[i].y, num[i].wei));
vet[num[i].y].push_back(Node(num[i].x, num[i].wei));
}
}
memset(sum,0,sizeof(sum));
res=0;
Dfs(1,0);
double exp = (double)(res) / (double)(n);
exp = exp / (double)(n - 1) * 2.0;
printf("%lld %.2lf\n", cnt, exp);
}
return 0;
}
2016 Multi-University Training Contest 1 A
原文:https://www.cnblogs.com/xtuteam222/p/9157952.html