题目描述
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<bits/stdc++.h>
using namespace std;
const int N=5000005;
int n,m,s;
double a[N][3];
struct node//定义结构体
{
int in;
int to;
double v;
};
struct node edge[N];
bool cmp(struct node a,struct node b)
{
return a.v<b.v;//对结构体中的x.v进行比较,>按降序排列,<按升序排列
}
int pre[N];
int fid(int x)//查找
{
if(pre[x]==x)
return x;
else
{
pre[x]=fid(pre[x]);
return pre[x];
}
}
void unin(int x,int y)//合并
{
pre[fid(x)]=fid(y);
}
void kruskal()
{
int w=0;
double k=0.00;//要求结果保留两位小数,其他数据也要为小数
for(int i=1; i<=s; i++)
{
if(fid(edge[i].in)!=fid(edge[i].to))
{
w++;
k+=sqrt(edge[i].v);
unin(edge[i].in,edge[i].to);
//cout<<"k="<<k<<endl;
}
else
continue;
if(w==n-1)
{
cout<<setiosflags(ios::fixed)<<setprecision(2);//可以让结果保留2位小数,如果是保留多位小数就将括号里面的数字改为你想保留的位数
cout<<k;
return ;
}
}
}
int main()
{
cin>>n>>m;
for(int i=1; i<=n; i++)
{
pre[i]=i;
cin>>a[i][0]>>a[i][1];//输入x坐标和y坐标
}
s=0;
for(int i=1; i<=n; i++)//可求出任意两点间的路径长度
{
for(int j=i+1; j<=n; j++)//因为是无向图,避免重复,减小时间复杂度
{
s++;
edge[s].in=i;
edge[s].to=j;
edge[s].v=abs(a[i][0]-a[j][0])*abs(a[i][0]-a[j][0])+abs(a[i][1]-a[j][1])*abs(a[i][1]-a[j][1]);
}
}
int b,c;
for(int i=1; i<=m; i++)//将已经相连的两点间的路径记为0.00
{
cin>>b>>c;
s++;
edge[s].in=b;
edge[s].to=c;
edge[s].v=0.00;
}
sort(edge+1,edge+s+1,cmp);//输入结构体变量
//for(int i=1;i<=s;i++)
//cout<<endl<<edge[i].in<<" "<<edge[i].to<<" "<<edge[i].v<<endl;
kruskal();
}
题目背景
小杉坐在教室里,透过口袋一样的窗户看口袋一样的天空。
有很多云飘在那里,看起来很漂亮,小杉想摘下那样美的几朵云,做成棉花糖。
题目描述
给你云朵的个数 NN,再给你 MM 个关系,表示哪些云朵可以连在一起。
现在小杉要把所有云朵连成 KK 个棉花糖,一个棉花糖最少要用掉一朵云,小杉想知道他怎么连,花费的代价最小。
输入格式
第一行有三个数 N,M,KN,M,K。
接下来 MM 行每行三个数 X,Y,LX,Y,L,表示XX云和 YY 云可以通过 LL 的代价连在一起。
输出格式
对每组数据输出一行,仅有一个整数,表示最小的代价。
如果怎么连都连不出 KK 个棉花糖,请输出 No Answer
。
输入输出样例
输入 #1复制
3 1 2 1 2 1
输出 #1复制
1
说明/提示
对于 30\%30% 的数据,N \le 100N≤100,M \le 10^3M≤103;
对于 100\%100% 的数据,1 \le N \le 10^31≤N≤103,1 \le M \le 10^41≤M≤104,1 \le K \le 101≤K≤10,1 \le X,Y \le N1≤X,Y≤N,0 \le L<10^40≤L<104。
#include<bits/stdc++.h>
using namespace std;
const int N=500005;
int n,m,l;
struct node//定义结构体
{
int in;
int to;
int v;
};
struct node edge[N];
bool cmp(struct node a,struct node b)
{
return a.v<b.v;//对结构体中的x.v进行比较,>按降序排列,<按升序排列
}
int pre[N];
int fid(int x)//查找
{
if(pre[x]==x)
return x;
else
{
pre[x]=fid(pre[x]);
return pre[x];
}
}
void unin(int x,int y)//合并
{
pre[fid(x)]=fid(y);
}
void kruskal()
{
int s=0,k=0;
for(int i=1;i<=m;i++)
{
if(fid(edge[i].in)!=fid(edge[i].to))
{
s++;
k+=edge[i].v;
unin(edge[i].in,edge[i].to);
//cout<<"k="<<k<<endl;
}
else
continue;
if(s==n-l)//求解答案的关键
{
cout<<k;
return ;//整个函数停止
}
}
cout<<"No Answer";
}
int main()
{
cin>>n>>m>>l;
for(int i=1;i<=m;i++)
{
cin>>edge[i].in>>edge[i].to>>edge[i].v;
pre[i]=i;
}
sort(edge+1,edge+m+1,cmp);//输入结构体变量
// for(int i=1;i<=m;i++)
//cout<<edge[i].in<<" "<<edge[i].to<<" "<<edge[i].v<<endl;
kruskal();
}