PTA_数据结构与算法_7-10 公路村村通 (30分)

现有村落间道路的统计数据表中,列出了有可能建设成标准公路的若干条道路的成本,求使每个村落都有公路连通所需要的最低成本。

输入格式:
输入数据包括城镇数目正整数N(≤1000)和候选道路数目M(≤3N);随后的M行对应M条道路,每行给出3个正整数,分别是该条道路直接连通的两个城镇的编号以及该道路改建的预算成本。为简单起见,城镇从1到N编号。

输出格式:
输出村村通需要的最低成本。如果输入数据不足以保证畅通,则输出−1,表示需要建设更多公路。

输入样例:

6 15
1 2 5
1 3 3
1 4 7
1 5 4
1 6 2
2 3 4
2 4 6
2 5 2
2 6 6
3 4 6
3 5 1
3 6 1
4 5 10
4 6 8
5 6 3

输出样例:

12

代码:

#include<cstdio>
#include<algorithm>
using namespace std;

const int MAXN = 1001;
int N, M, Father[MAXN],cnt=0, Cost=0;//Father为每棵树的根节点,cnt为已收入的边的条数,Cost为最终费用
struct Enode{//边节点
    int v1, v2, w;
}E[3*MAXN];
bool cmp(Enode E1, Enode E2);//sort函数的比较方法,从小到大
int FindFather(int x);//找到一个节点所在树的根节点
int Kruskal();//若有最小生成树则返回最小花费,否则返回-1

int main()
{
    scanf("%d%d",&N, &M);
    for(int i=0;i<M;i++)
        scanf("%d%d%d",&E[i].v1, &E[i].v2, &E[i].w);
    printf("%d\n",Kruskal());
    return 0;
}

int Kruskal(){
    for(int i=1;i<=N;i++)//每个节点看成一棵树,根节点为其自身,注意是从1编号
        Father[i] = i;
    sort(E, E+M, cmp);//每个节点按权重排序,之后按此顺序检查边的两个顶点是否属于同一棵树并决定是否收入
    for(int i=0;i<M;i++){
        int Fa1 = FindFather(E[i].v1), Fa2 = FindFather(E[i].v2);//暂存一条边的两个顶点所在树的根节点
        if(Fa1 != Fa2){//如果不属于同一棵树,即收入此边不会构成回路
            Father[Fa2] = Fa1;//把v2根节点改为v1根节点,即合并两棵树,收入这条边
            Cost += E[i].w;
            cnt++;
        }
        if(cnt==N-1) break;//收入N-1条边即算法结束
    }
    return cnt==N-1 ? Cost : -1;//若无最小生成树则返回-1
}

bool cmp(Enode E1, Enode E2){
    return E1.w < E2.w;
}

int FindFather(int x){
    if(Father[x]==x) return x;
    else return Father[x] = FindFather(Father[x]);
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

dgyzmyx_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值