最小生成树kruskal

题意描述

约翰有N个牧场,编号依次为1到N。每个牧场里住着一头奶牛。连接这些牧场的有P条道路,每条道路都是双向的。第j条道路连接的是牧场Sj和Ej,通行需要Lj的时间。两牧场之间最多只有一条道路。约翰打算在保持各牧场连通的情况下去掉尽量多的道路。

约翰知道,在道路被强拆后,奶牛会非常伤心,所以他计划拆除道路之后就去忽悠她们。约翰可以选择从任意一个牧场出发开始他维稳工作。当他走访完所有的奶牛之后,还要回到他的出发地。每次路过牧场i的时候,他必须花Ci的时间和奶牛交谈,即使之前已经做过工作了,也要留下来再谈一次。注意约翰在出发和回去的时候,都要和出发地的奶牛谈一次话。请你计算一下,约翰要拆除哪些道路,才能让忽悠奶牛的时间变得最少?

分析

我们读题可以注意到

  • 约翰打算在保持各牧场连通的情况下去掉尽量多的道路。
  • 约翰要拆除哪些道路,才能让忽悠奶牛的时间变得最少?
  • 从任意一个牧场出发开始他维稳工作
  • 当他走访完所有的奶牛之后,还要回到他的出发地。每次路过牧场i的时候,他必须花Ci的时间和奶牛交谈,即使之前已经做过工作了,也要留下来再谈一次。

我们可以得出这是一道最小生成树的裸题

但是这个题有一些不同,就是我们的边权是等于起点的权加上终点的权加上边权*2,为什么呢,可以举一个最简单的例子,假设从a到b还要回到a,显然我们可以得到以上的结论。

代码

#include<bits/stdc++.h>
using namespace std;
struct rep{
	int x,y,z;
}edge[100005];
int n,m,ans=0x3f3f3f3f;
int c[100005];
int fa[100005];
bool cmp(rep a,rep b){
return a.z<b.z;
}
int get(int x)
{
	if(x==fa[x])
	return x;
	else return fa[x]=get(fa[x]);//return一定要记得写
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
cin>>c[i],ans=min(ans,c[i]);	//因为还得返回原来的位置,所以我们对每个牧场的时间取min,意味着,我们从时间最小的位置出发可以获取最小时间
 for(int i=1;i<=n;i++)
 fa[i]=i; 
 for(int i=1;i<=m;i++)
 {
 int x,y,z;
 cin>>x>>y>>z;
 edge[i].x=x;
 edge[i].y=y;
 edge[i].z=c[x]+c[y]+z*2;
 }
 sort(edge+1,edge+1+m,cmp);
 for(int i=1;i<=m;i++)
 {
 	int px,py;
 	px=get(edge[i].x);
 	py=get(edge[i].y);
 	if(px==py)
 	continue;
  fa[px]=py;
 	ans+=edge[i].z;
 }
 cout<<ans;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值