题意
一个图,求最小生成树,输出权值和 && 任给两点的期望
分析
这题关键是如何求期望。
每条边权值都不一样,说明最小生成树是唯一的(不唯一怎么办?)
在求最小生成树时顺便把树建好,然后dfs找每条边经过了多少次,求得这条边的花费 num×(n−num)×cost
∑边的花费÷n(n−1)2(种数)
代码
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<string>
#include<vector>
#include<cctype>
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<iomanip>
#include<sstream>
#include<limits>
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
const ll INF = 1e18;
const int maxn = 1e6+10;
const ll MOD = 1000000007;
const double EPS = 1e-10;
const double Pi = acos(-1.0);
struct Node {
ll x, y, val;
bool operator <(const Node A)const {
return val<A.val;
}
}mp[maxn];
int f[maxn];
int Find(int x)
{
if (f[x] != x) return f[x] = Find(f[x]);
return f[x];
}
struct Edge{ ll to,cost;};
vector<Edge> G[maxn];
inline ll kru(ll n, ll m)
{
sort(mp, mp + m);
ll sum = 0, cnt = 0;
for (int i = 0; i <= n; i++)
{
G[i].clear();f[i] = i;
}
for (int i = 0; i < m; i++)
{
ll t1 = Find(mp[i].x);
ll t2 = Find(mp[i].y);
if (t1 == t2) continue;
G[mp[i].x].push_back({mp[i].y,mp[i].val});
G[mp[i].y].push_back({mp[i].x,mp[i].val});
sum += mp[i].val;
f[t1] = t2;
cnt++;
if (cnt == n - 1) break;
}
return sum;
}
bool vis[maxn];
ll Max,n,m;
ll dfs(int x)
{
vis[x] = false;
ll cnt = 0;
for(int i = 0; i < G[x].size(); i++)
{
if (vis[G[x][i].to])
{
ll res = dfs(G[x][i].to);
cnt += res;
Max += res*(n-res)*G[x][i].cost;
}
}
return cnt+1;
}
int main(){
#ifdef LOCAL
freopen("C:\\Users\\lanjiaming\\Desktop\\acm\\in.txt","r",stdin);
//freopen("output.txt","w",stdout);
#endif
//ios_base::sync_with_stdio(0);
int T;
scanf("%d",&T);
while(T--)
{
scanf("%lld%lld",&n,&m);
if(n==0||m==0)
{
printf("0 0.00\n");
continue;
}
for (int i = 0; i < m; i++) scanf("%lld %lld %lld",&mp[i].x,&mp[i].y,&mp[i].val);
ll ans = kru(n,m);
memset(vis,true,sizeof vis);
Max = 0;
int k = 1;
for( ;k <= n; k++)
if ( G[k].size() == 1) break;
ll res = dfs(k);
double exp = n*(n-1)/2;
exp = Max / exp;
printf("%lld %.2f\n",ans,exp);
}
return 0;
}