天空之城(最小生成树模板题)

题目描述

**链接:https://ac.nowcoder.com/acm/contest/9986/J
来源:牛客网

天空之城有5个小镇,名字分别为Ada, Aed, Akk, Orz, Apq,他们也有相互的路径长度。

希达早已期盼着天空之城,如今她登上了天空之城,就想走遍天空之城的每一个城市,但是她希望自己走的路的长度越小越好,以节省体力和节约时间。

巴鲁同意了,但由于他是主力(男孩子嘛),需要帮希达计算出走遍所有城市的最短路径长度。

由于天空之城具有魔力,如果希达想再走一次自己之前走过的路,则她可以在这条路上不花费任何时间。

但是天空之城的城市太多了,他实在计算不过来,只得请你来帮帮忙了。**

输入描述

第一行,输入n,q, 表示有n个城市,q条边;
第二行,输入一个名字tmp,表示希达想要从tmp城市开始行走;
接下来q行,每行输入两个名字a,b和一个数字val, 表示a城市与b城市之间的距离为val.(注意可能有重边和自环)

输出描述

帮助巴鲁计算出最短的路径长度,如果无法走遍所有城市,输出“No!”。

样例输入

5 5
Orz
Ada Aed 5
Orz Ada 6
Apq Aed 8
Akk Apq 12
Aed Orz 3

样例输出

28

备注

多组输入输出(以EOF结束),保证数据组数不超过 10 。
1 <= n <= 5000, 1 <= q <= 200000, 1 <= val <= 1e9. 每个城市的名字长度不超过10。

思路

这题的提示在于这句话“由于天空之城具有魔力,如果希达想再走一次自己之前走过的路,则她可以在这条路上不花费任何时间。”由此可以看出需要用到最小生成树来解题。由于题目给的地名是字符串,所以存图的时候需要用到map函数,将字符串与城市编号形成映射。在此附上我的AC代码

#include<iostream>
#include<algorithm>
#include<vector> 
#include<map>
#include<string>
using namespace std;
typedef long long ll;

struct bian{
	int u, v, chang;
} a[200010];

map<string, int> mp;
string s, s1, s2;

int n, m;
int fa[10010];
int find(int x){
	if(x==fa[x]) return x;
	return fa[x] = find(fa[x]);
}

void merge(int x, int y){
	fa[find(x)] = find(y);
}

bool cmp(bian p, bian q){
	return p.chang<q.chang;
}

int main()
{
	while(scanf("%d%d", &n, &m)!=EOF){
        mp.clear();
		cin >> s;
		int cnt=0, x;
		for(int i=1;i<=m;i++){
			cin >> s1 >> s2 >> x;
			if(mp.find(s1) == mp.end()) mp[s1] = ++cnt;
			if(mp.find(s2) == mp.end()) mp[s2] = ++cnt;
			a[i].chang=x;
			a[i].u=mp[s1];
			a[i].v=mp[s2];
		}
	
		for(int i=1;i<=n;i++)
			fa[i] = i;
	
		sort(a+1, a+1+m, cmp);
	
		ll ans=0, num=0;
		for(int i=1;i<=m;i++){
			if(find(a[i].u)!=find(a[i].v)){
				merge(a[i].u, a[i].v);
				ans+=a[i].chang;
				num++;
			}
		}
		if(num<n-1) printf("No!\n");
		else printf("%lld\n", ans);
	}
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值