【c++图论】洛谷P2872 [USACO07DEC]Building Roads S

题目描述

Farmer John had just acquired several new farms! He wants to connect the farms with roads so that he can travel from any farm to any other farm via a sequence of roads; roads already connect some of the farms.

Each of the N (1 ≤ N ≤ 1,000) farms (conveniently numbered 1..N) is represented by a position (Xi, Yi) on the plane (0 ≤ Xi ≤ 1,000,000; 0 ≤ Yi ≤ 1,000,000). Given the preexisting M roads (1 ≤ M ≤ 1,000) as pairs of connected farms, help Farmer John determine the smallest length of additional roads he must build to connect all his farms.

给定 nn 个点的坐标,第 ii 个点的坐标为 (x_i,y_i)(xi​,yi​),这 nn 个点编号为 11 到 nn。给定 mm 条边,第 ii 条边连接第 u_iui​ 个点和第 v_ivi​ 个点。现在要求你添加一些边,并且能使得任意一点都可以连通其他所有点。求添加的边的总长度的最小值

输入格式

* Line 1: Two space-separated integers: N and M

* Lines 2..N+1: Two space-separated integers: Xi and Yi

* Lines N+2..N+M+2: Two space-separated integers: i and j, indicating that there is already a road connecting the farm i and farm j.

第一行两个整数 n,mn,m 代表点数与边数。
接下来 nn 行每行两个整数 x_i,y_ixi​,yi​ 代表第 ii 个点的坐标。
接下来 mm 行每行两个整数 u_i,v_iui​,vi​ 代表第 ii 条边连接第 u_iui​ 个点和第 v_ivi​ 个点。

输出格式

* Line 1: Smallest length of additional roads required to connect all farms, printed without rounding to two decimal places. Be sure to calculate distances as 64-bit floating point numbers.

一行一个实数代表添加的边的最小长度,要求保留两位小数,为了避免误差, 请用 6464 位实型变量进行计算。

输入输出样例

输入 #1复制

4 1
1 1
3 1
2 3
4 3
1 4

输出 #1复制

4.00

说明/提示

数据规模与约定

对于 100\%100% 的整数,1 \le n,m \le 10001≤n,m≤1000,1 \le x_i,y_i \le 10^61≤xi​,yi​≤106,1 \le u_i,v_i \le n1≤ui​,vi​≤n。

说明

Translated by 一只书虫仔。

这道题有没有很熟悉↓

类似可见

具体做法 

#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int n,m;
long long f[10100101];
int ax[10100010];
int ay[10100010];
int ecnt=0;
struct node{
	long long u,v,w,next;
	bool operator <(const node &a)const{
		return w<a.w;//注意排序顺序和结构体排序对象
	}
}e[10101000];
void addedge(long long  u,long long v,long long w){
	e[++ecnt].u=u;
	e[ecnt].v=v;
	e[ecnt].w=w;
}
int getf(int x){
	return x==f[x]?x:f[x]=getf(f[x]);
}
long long xx(int x,int ww){
	return 1ll*(ax[x]-ax[ww])*(ax[x]-ax[ww])+1ll*(ay[x]-ay[ww])*(ay[x]-ay[ww]);//先不开方,不然比较难处理,在后文计算的时候会进行处理;
}
//1ll*指的是转成lang lang 类型,如果不加可能会结果超int变为负数;
int main(){
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		cin>>ax[i]>>ay[i];
	}
	for(int i=1;i<n;i++){
		for(int j=i+1;j<=n;j++){
			addedge(i,j,xx(i,j));//注意循环内容,为了避免循环到同一个点;
		}
	}
	for(int j=1;j<=m;j++){

		int a,b;
		cin>>a>>b;
		addedge(a,b,0);//这里不建议直接cin>>e[i].u>>e[i].v>>e[i].w;因为这道题是个单向边,但是双向边直接输入无法处理,所以建议写addedge函数;
	}
	for(int i=1;i<=n;i++){
		f[i]=i;//所有点的爹都是自己
	}
	sort(e+1,e+1+ecnt);
int	cnt=0;
double aas=0;
	for(int i=1;i<=ecnt;i++){//ecnt是边得个数
		int u=getf(e[i].u);
		int v=getf(e[i].v);//两个点找爹
		if(u!=v){
			cnt++;//边数++
			aas+=sqrt(e[i].w);//这里开方处理,注意aas数据类型;
			f[u]=v;//统一爹
		}
		if(cnt==n-1){
			break;
		}
	}
	
	printf("%.2lf",aas);//注意题目输出格式
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

贤鱼不闲

一分钱也是爱!!!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值