题目:道路建设
思路:
假设原来没有路径相连,那么就是求原图的最小生成树。
再回顾kruskal算法的加边过程,可以发现只用把原有的边的边权变为0,再求最小生成树时它们就一定会最先被添加了。
代码:
#include<bits/stdc++.h>
using namespace std;
#define maxn 1000
#define db double
#define ll long long
struct Edge{
int x,y;
db z;
Edge(){}
Edge(int xx,int yy,db zz) {
x=xx,y=yy,z=zz;
}
bool operator < (const Edge& oth) const {
return z<oth.z;
}
};
int n,m;
vector<Edge> e;
int fa[maxn+5]={0};
int X[maxn+5],Y[maxn+5];
db findd(int x1,int y1,int x2,int y2){
return sqrt(((ll)x1-x2)*(x1-x2)+((ll)y1-y2)*(y1-y2));
}
void readin(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) {
scanf("%d%d",&X[i],&Y[i]);
for(int j=1;j<i;j++) {
e.push_back(Edge(j,i,findd(X[i],Y[i],X[j],Y[j])));
}
}
for(int i=1;i<=m;i++) {
int x,y;
scanf("%d%d",&x,&y);
e.push_back(Edge(x,y,0));
}
}
int find(int x){
if(-1==fa[x]) return x;
else return fa[x]=find(fa[x]);
}
void init(){
sort(e.begin(),e.end());
memset(fa,-1,sizeof(fa));
}
db kruskal(){
init();
db ans=0;
for(int i=0;i<e.size();i++) {
int x=e[i].x,y=e[i].y;
int f1=find(x),f2=find(y);
if(f1==f2) continue;
else fa[f1]=f2;
ans+=e[i].z;
}
return ans;
}
int main(){
readin();
db ans=kruskal();
printf("%.2lf",ans);
return 0;
}