洛谷 P1550 [USACO08OCT]打井Watering Hole

题目:打井

思路:
现在图中加入一个节点0,并向1~n引出一条权值为wi的边。
这样就相当于默认在节点0打井了,在新图中求出最小生成树就好。

代码:

#include<bits/stdc++.h>
using namespace std;

#define maxn 300

struct Edge{
    int x,y,z;
    Edge(){}
    Edge(int xx,int yy,int zz) {
        x=xx,y=yy,z=zz;
    }
    bool operator < (const Edge& oth) const {
        return z<oth.z;
    }
};

int n;
vector<Edge> e;
int fa[maxn+5]={0};

void readin(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++) {
        int x;
        scanf("%d",&x);
        e.push_back(Edge(0,i,x));
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            int x;
            scanf("%d",&x);
            if(j<=i) continue;
            else e.push_back(Edge(i,j,x));
        }
    }
}

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));
}

int kruskal(){
    init();
    int 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();
    int ans=kruskal();
    printf("%d",ans);
    return 0;
}

猜你喜欢

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