牛客IOI周赛22-普及组 路线规划 查并集

路线规划

戳我找原题

成为热门手记人偶的薇尔莉特伊芙嘉登最近收到了非常多的委托,这些委托者分散在世界的各地,各个国家都有。但正值战争的尾声,穿行于各个国家之间是非常危险的,一路上会有许多的敌人,这些敌人或许不会对我们的薇尔莉特构成威胁,但是依然会浪费她的时间,手记人偶的时间可是非常宝贵的。现给定有 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;
}

附:初来乍到,如果有不足之处,恳请各位大牛指正,如果题解有错误或者没写清楚的地方也欢迎在评论区提问~

猜你喜欢

转载自blog.csdn.net/qq_34832548/article/details/113100983