【HDU】5723 Abandoned country(2016 Multi-University)

18 篇文章 0 订阅
14 篇文章 0 订阅

Abandoned country


题目链接


题目大意

    有一个村子里面修公路,每条公路都有一个修建价值,现在让你把所有村子连起来,求最小价值,顺便求出所有公路的平均值。


题解

最小生成树+DFS

    首先肯定是一个最小生成树了,主要是求所有路径的平均值。
    可以看到是一颗树,想到在DFS的同时记录数据来求这颗树的所有路径和,我们画图发现,当前边对sum的贡献是

+

    所以我们记录一个
last

    每次求完一颗子树的时候加进总结过就行了。

    这个题方法挺多的,好像还看到有人用DP?


代码

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#define maxm 1000010
#define maxn 100010
#define LL long long

using namespace std;

struct edge
{
    int u,v,next,d;
    bool operator<(const edge &x) const
    {
        return d<x.d;
    }
};
edge e[maxm<<1],E[maxm<<1];
int pre[maxn],nume,numE,f[maxn];
LL T,n,m;
LL sum,tag;

void addedge(edge e[],int u,int v,int d,int &nume)
{
    e[nume].u=u;
    e[nume].v=v;
    e[nume].d=d;
    e[nume].next=pre[u];
    pre[u]=nume++;
}

int getfather(int k)
{
    if (f[k]==k) return k;
    else return f[k]=getfather(f[k]);
}

LL dfs(int u,int father,LL dis,LL last)
{
    LL p=0,c,flag=tag+1;
    sum+=last;
    last+=tag*dis;
    tag++;
    for (int i=pre[u];i!=-1;i=E[i].next)
    {
        int v=E[i].v;
        if (v!=father)
        {
            sum+=(tag)*E[i].d;
            c=dfs(v,u,E[i].d,last+p);
            p+=c+(tag-flag)*E[i].d;
            flag=tag;
        }
    }
    return p;
}

int main()
{
    scanf("%I64d",&T);
    while (T--)
    {
        memset(f,0,sizeof(f));
        memset(e,0,sizeof(e));
        memset(pre,-1,sizeof(pre));
        memset(E,0,sizeof(E));
        nume=0; numE=0; sum=0; tag=0;
        int u,v,fu,fv,d;
        scanf("%I64d%I64d",&n,&m);
        for (int i=0;i<m;i++)
        {
            scanf("%d%d%d",&u,&v,&d);
            addedge(e,u,v,d,nume);
            addedge(e,v,u,d,nume);
        }
        sort(e,e+nume);
        LL ans=0;
        for (int i=0;i<=n;i++) f[i]=i;
        memset(pre,-1,sizeof(pre));
        for (int i=0;i<nume;i++)
        {
            u=e[i].u; v=e[i].v;
            fu=getfather(u); fv=getfather(v);
            if (fu!=fv)
            {
                f[fv]=fu; ans+=e[i].d;
                addedge(E,u,v,e[i].d,numE);
                addedge(E,v,u,e[i].d,numE);
            }
        }
        dfs(1,0,0,0);
        LL nn= (n-1)*n/2;
        double exp=(double) sum/nn;
        printf("%I64d %.2lf\n",ans,exp);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值