2016 Multi-University Training Contest 1 A

题意要求跑最小生成树,然后求出任意两点距离的期望。

做法是用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;
}

  

猜你喜欢

转载自www.cnblogs.com/xtuteam222/p/9157952.html