ZJNU 1213

某个村庄i可以打一口井取水花费费用Wi,也可以与有水的村庄连接取水

又因为不可能没有一个村庄不打井(即至少有一个村庄打井,其余村庄连向它)

实际上就可以理解为,将水井看作第N+1个村庄,需要有村庄与这个N+1村庄相连,才能保证所有村庄有水

而村庄i连接到村庄N+1的费用,就可以直接理解为打井的费用Wi

其余部分使用Kruskal最小生成树即可

#include<cstdio>
#include<algorithm>
using namespace std;
struct tube{
    int from,to,cost;
    bool operator < (const tube &a) const{
        return cost<a.cost;
    }
}p[90001];
int gp[301];
int find(int a){
    return a==gp[a]?a:(gp[a]=find(gp[a]));
}
int main(){
    int i,j,N,d,cnt=0,k=0,sum;
    scanf("%d",&N);
    for(i=1;i<=N;i++){
        scanf("%d",&d);
        p[cnt].from=i;
        p[cnt].to=N+1;
        p[cnt++].cost=d;
        gp[i]=i;
    }
    for(i=1;i<=N;i++)
        for(j=1;j<=N;j++){
            scanf("%d",&d);
            if(i==j)
                continue;
            p[cnt].from=i;
            p[cnt].to=j;
            p[cnt++].cost=d;
        }
    sort(p,p+cnt);
    for(sum=i=0;i<cnt;i++){
        if(k==N)
            break;
        if(find(p[i].from)!=find(p[i].to)){
            gp[find(p[i].to)]=find(p[i].from);
            sum+=p[i].cost;
            k++;
        }
    }
    printf("%d
",sum);
    
    return 0;
}
原文地址:https://www.cnblogs.com/stelayuri/p/12233534.html