洛谷P2212
题目大概意思是有n块田地,给出坐标xi,yi,铺设两块田地之间水管的费用为两点间距离的平方,水管工人只铺设费用大于等于c的水管,问是否能将n块田地连通,如果可以输出最小费用,如果不行输出-1.
kruskal做法
很显然是个板子题,我们只需要把费用大于等于c的边加进去就行,然后遍历所有边,看是否能形成连通图,如果能就输出费用即可。
注意由于数据较大,建边的时候每对点建一条边即可,不然TLE on test 9。
代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
const int mod=1e9+7;
const int INF=0x3f3f3f3f;
const double EPS=1e-6;
typedef long long ll;
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
int x[N],y[N];
int fa[N],sizes[N];
int dis(int i,int j)
{
return (x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]);
}
struct node
{
int x,y,dis;
}e[5000010];
int tot=0;
void addedge(int u,int v)
{
tot++;
e[tot].x=u;
e[tot].y=v;
e[tot].dis=dis(u,v);
}
bool cmp(node a,node b)
{
return a.dis<b.dis;
}
int find(int x)
{
if(x==fa[x])
return x;
return fa[x]=find(fa[x]);
}
int main()
{
IOS;
int n,c;
cin>>n>>c;
for(int i=1;i<=n;i++)
fa[i]=i,sizes[i]=1;
for(int i=1;i<=n;i++)
{
cin>>x[i]>>y[i];
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=i;j++)
{
if(i!=j)
{
if(dis(i,j)>=c)
{
addedge(i,j);
}
}
}
}
sort(e+1,e+tot+1,cmp);
int cnt=n;
ll sum=0;
for(int i=1;i<=tot;i++)
{
if(cnt==1)
{
break;
}
int xx=find(e[i].x);
int yy=find(e[i].y);
if(xx!=yy)
{
if(sizes[xx]>=sizes[yy])
{
fa[yy]=xx;
sizes[xx]+=sizes[yy];
}
else
{
fa[xx]=yy;
sizes[yy]+=sizes[xx];
}
sum+=e[i].dis;
cnt--;
}
}
if(cnt==1)
cout<<sum;
else
cout<<-1;
}
来源:CSDN
作者:Joker_He
链接:https://blog.csdn.net/Joker_He/article/details/104107618