P2872 [USACO07DEC]Building Roads S(最小生成树)
Posted 行码棋
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P2872 [USACO07DEC]Building Roads S(最小生成树)相关的知识,希望对你有一定的参考价值。
本题是最小生成树的相关题目,初始情况存在几条边,剩下的边需要自己选。
思路:
首先需要把所有点之间的距离求出来存到边的数组中,然后对边按权值从小到大进行排序,对已经存在的边重新再加入到边的数组中,把存在的边的权值设为0,那么之后首先就会选到权值为0的边,然后就按kruskal的模板代码写就行了。
注意:
1.精度问题
求边之间的距离时,sqrt()里面的参数应该是double型的,如果是int型,就会出现精度问题,需要对求出的数据进行强制转换
2.并查集初始化
#include<bits/stdc++.h>
#define fi first
#define se second
using namespace std;
typedef long long ll;
typedef pair<int ,double> pii;
const int inf = 0x3f3f3f3f;
const int N = 1e3+10;
int n,m;
int x[N],y[N],f[N];
pair<int,pii > e[N*N];//存储边的起点,终点和权值
ll find(ll x){return x==f[x] ? x :(f[x]=find(f[x]));}//并查集
bool cmp(pair<int,pii > a,pair<int,pii > b)
{
return a.se.se<b.se.se;
}
int main()
{
// freopen("inn.txt","r",stdin);
int cnt = 0;
cin>>n>>m;
int t=n;
while(t--)
{
int xx,yy;
cin>>xx>>yy;
x[++cnt]=xx,y[cnt]=yy;
}
//计算所有点之间的距离
int cur=0;
for(int i=1;i<=n;i++)
{
for(int j=i+1;j<=n;j++)
{
double dis = (double)sqrt((double)(x[i]-x[j])*(x[i]-x[j])+(double)(y[i]-y[j])*(y[i]-y[j]));
e[++cur]={i,{j,dis}};
}
}
// for(int i=1;i<=cur;i++) cout<<e[i].second.se<< " ";
//对已存在的边进行存储
while(m--)
{
int a,b;
cin>>a>>b;
e[++cur]={a,{b,0}};
}
//对边按权值进行排序
sort(e+1,e+1+cur,cmp);
// cout<< '\\n';
// for(int i=1;i<=cur;i++) cout<<e[i].fi<< " "<<e[i].se.fi<< " "<<e[i].se.se <<'\\n';
//并查集初始化
for(int i=1;i<=n;i++) f[i]=i;
double ans=0;
for(int i=1;i<=cur;i++)
{
int a=find(e[i].fi);
int b=find(e[i].se.fi);
if(a==b)continue;
f[b]=a;
ans += e[i].se.se;
}
printf("%.2lf\\n",ans);
return 0;
}
以上是关于P2872 [USACO07DEC]Building Roads S(最小生成树)的主要内容,如果未能解决你的问题,请参考以下文章
P2872 [USACO07DEC]Building Roads S
洛谷 P2872 [USACO07DEC]Building Roads S
P2872 [USACO07DEC]Building Roads Skruskal
P2872 [USACO07DEC]Building Roads S(最小生成树)