链接:点击打开链接
题意:在最小生成树的基础上求出任意两点间距离的期望
代码:
#include <vector>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <algorithm>
using namespace std;
const long long SIZE=100005;
long long n,dp[SIZE],num[SIZE],used[SIZE];
struct node{
long long to,cost;
};
vector<node> G[SIZE];
void dfs1(long long s,long long sum){
long long i,tmp;
dp[1]+=sum; //求出根节点的到其他节点的和
used[s]=1; //和每个节点的子节点数
for(i=0;i<G[s].size();i++){
tmp=G[s][i].to;
if(!used[tmp]){
dfs1(tmp,sum+G[s][i].cost);
num[s]+=num[tmp];
}
}
}
void dfs2(long long s){
long long i,tmp;
used[s]=1;
for(i=0;i<G[s].size();i++){
tmp=G[s][i].to;
if(!used[tmp]){
dp[tmp]+=(dp[s]+(n-num[tmp])*G[s][i].cost-num[tmp]*G[s][i].cost);
dfs2(tmp);
} //根据每个节点儿子节点的个数求出每个节点
} //到其他所有节点的和
}
long long V,E;
long long par[100005],ran[100005],vis[100005];
void init(long long n){
long long i;
for(i=0;i<=n;i++){
ran[i]=0;
par[i]=i;
}
}
long long find(long long x){
if(par[x]==x)
return x;
return par[x]=find(par[x]);
}
void unite(long long x,long long y){
x=find(x);
y=find(y);
if(x==y)
return;
if(ran[x]<ran[y])
par[x]=y;
else{
par[y]=x;
if(ran[x]==ran[y])
ran[x]++;
}
}
bool same(long long x,long long y){
return find(x)==find(y);
}
struct node1{
long long u,v,cost;
};
bool cmp(node1 a,node1 b){
return a.cost<b.cost;
}
node1 es[1000005];
long long kruskal(){
long long i;
long long res=0;
init(V);
sort(es,es+E,cmp);
for(i=0;i<E;i++){
node1 e=es[i];
if(!same(e.u,e.v)){
unite(e.u,e.v);
G[e.u].push_back((node){e.v,e.cost});
G[e.v].push_back((node){e.u,e.cost});
res+=e.cost;
}
}
return res;
} //最小生成树
int main(){ //跟51nod1405几乎一样
long long a,b,w,m,i,t,ans,sum; //http://blog.csdn.net/stay_accept/article/details/50835286
scanf("%I64d",&t);
while(t--){
scanf("%I64d%I64d",&n,&m);
V=n,E=m;
for(i=1;i<=n;i++)
G[i].clear();
memset(vis,0,sizeof(vis));
for(i=0;i<E;i++)
scanf("%I64d%I64d%I64d",&es[i].u,&es[i].v,&es[i].cost);
ans=kruskal();
fill(num,num+n+1,1);
memset(dp,0,sizeof(dp));
memset(used,0,sizeof(used));
dfs1(1,0);
memset(used,0,sizeof(used));
dfs2(1);
sum=0;
for(i=1;i<=n;i++)
sum+=dp[i];
printf("%I64d %.2lf\n",ans,sum*1.0/(n*(n-1)));
}
return 0;
}