路线规划
成为热门手记人偶的薇尔莉特伊芙嘉登最近收到了非常多的委托,这些委托者分散在世界的各地,各个国家都有。但正值战争的尾声,穿行于各个国家之间是非常危险的,一路上会有许多的敌人,这些敌人或许不会对我们的薇尔莉特构成威胁,但是依然会浪费她的时间,手记人偶的时间可是非常宝贵的。现给定有 n 个结点,m 条边的图,除了 1 号结点外,其余 n-1 个结点代表着分散在各地的委托者,他们之间由 m 条道路连接,数据保证图是连通的。现在第 i 道路上有 ai个敌人,每打晕 1 个敌人需要 1 个单位时间。可以理解为通行第 i 条路所需要的时间 ai (1 ≤ i ≤ m),当薇尔莉特经过一条道路时,仅仅会打晕该条路上的敌人,第一次打晕某条道路上的敌人后,下次经过该条道路仍需要打晕他们。
薇尔莉特从 1 号结点出发,完成所有的委托后还要回到 1 号结点,薇尔莉特希望自己拿出最好的状态去完成每一个委托,但记路这种小事情则会严重影响薇尔莉特的状态。
所以,请你帮帮我们的薇尔莉特,在 走过的路 最少的前提下,求出完成所有委托所需时间 T 的最小值。
PS:一条路只要被经过一次或以上即视为 走过的路
解题思路
经典的最小生成树模板题(kruskal算法)
感觉这应该是这次比赛中最简单的题
就不过多解释了
不懂建议看一下b站一个up对最小生成树的动画
讲的非常生动,强推
PS:因为是来回,所以最后答案记得*2
AC代码
#include <cstdio>
#include <algorithm>
using namespace std;
long long int f[10000001];
long long int find(int x) {
if(x==f[x])
return x;
return f[x]=find(f[x]);
}//查找父结点
struct Nebula {
long long int u,v,a;
bool operator<(const Nebula&t)const {
return a<t.a;
}
} s[8000001];
int main() {
long long int u,v,a;
int n,m;
scanf("%d %d",&n,&m);//输入数据
for(long long int i=1; i<=n; i++)f[i]=i;
for(int i=1; i<=m; i++)
scanf("%lld %lld %lld",&s[i].u,&s[i].v,&s[i].a);//将边的数据详细输入
sort(s+1,s+1+m);//排序 把边权按递增排序
long long int ans=0;
for(int i=1; i<=m; i++) {
long long int fv=find(s[i].v);
long long int fu=find(s[i].u);
if(fv==fu)//如果构成了环,跳过下一个
continue;
else {
ans+=s[i].a;
f[fv]=fu;
}
}
printf("%lld",ans*2);//来回答案*2
}
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
long long int f[10000001];
long long int find(int x) {
if(x==f[x])return x;
return f[x]=find(f[x]);
}
struct Nebula {
long long int u,v,a;
bool operator <(const Nebula&t)const {
return a<t.a;
}
} cx[200001];
int main() {
int n,m;
cin>>n>>m;
for(long long int i=1; i<=n; i++)
f[i]=i;
for(int i=1; i<=m; i++) {
long long int u,v,a;
cin>>u>>v>>a;
cx[i].u=u;
cx[i].a=a;
cx[i].v=v;
}
sort(cx+1,cx+1+m);
long long int ans=0;
for(int i=1; i<=m; i++) {
long long int fu=find(cx[i].u);
long long int fv=find(cx[i].v);
if(fu==fv)
continue;
else {
ans+=cx[i].a;
f[fv]=fu;
}
}
cout<<ans*2;
}
附:初来乍到,如果有不足之处,恳请各位大牛指正,如果题解有错误或者没写清楚的地方也欢迎在评论区提问~