题目描述
**链接: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;
}