2021牛客寒假算法基础集训营6 J.天空之城

J.天空之城

题目链接: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!”。

示例1:

输入
5 5
Orz
Ada Aed 5
Orz Ada 6
Apq Aed 8
Akk Apq 12
Aed Orz 3
输出
28
说明
Ada->Aed->Orz->Aed->Apq->Akk
备注:

多组输入输出(以EOF结束),保证数据组数不超过 10 。

1 <= n <= 5000, 1 <= q <= 200000, 1 <= val <= 1e9. 每个城市的名字长度不超过10。

保证∑q≤200000 。

解题思路:

最小生成树模板题 用map把string转换到数上(map <string, int> mp),然后即是n 个点 m 条边的最小生成树模板题。
最小生成树模板代码:
最小生成树之kruskal算法
最小生成树之prim算法

代码如下:

#include <iostream>
#include<algorithm>
#include<cstdio>
#include<string>
#include<map>
using namespace std;
#define ll long long
map <string, int> mp;
int n,m,cnt=0;
string s;
struct node{
	int x,y,p;
}a[200010];
int pre[10010];
bool cmp(node a,node b){
	return a.p<b.p;
}
int find(int x){
	if(x!=pre[x]){
		pre[x]=find(pre[x]);
	}
	return pre[x];
}
void merge(int x, int y){
	int fx=find(x),fy=find(y);
	if(fx!=fy) pre[fy]=fx;
}
int main(){
	while(scanf("%d%d",&n,&m)!=EOF){
		mp.clear();
		cnt=0;
		cin>>s;
		for (int i=1;i<=m;i++){
			string s1,s2;
			int x;
			cin>>s1>>s2>>x;
			if (mp.find(s1)==mp.end()) mp[s1]= ++cnt;
			if (mp.find(s2)==mp.end()) mp[s2]= ++cnt;
			a[i].x=mp[s1];
			a[i].y=mp[s2];
			a[i].p=x;
		}
		sort(a+1,a+1+m,cmp);
		for (int i=1;i<=n;i++)
			pre[i]=i;
		ll ans=0;
		int num=0;
		for (int i=1;i<=m;i++){
			if (find(a[i].x)!=find(a[i].y)){
				ans+=a[i].p;
				num++;
				merge(a[i].x,a[i].y);
			}
		}
		if (num<n-1) 
			printf("No!\n");
		else 
			printf("%lld\n",ans);
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值