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;
}