洛谷 P2872 [USACO07DEC]道路建设Building Roads

题目:道路建设

思路:
假设原来没有路径相连,那么就是求原图的最小生成树。
再回顾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;
}

猜你喜欢

转载自blog.csdn.net/rabbit_ZAR/article/details/81394900