某个村庄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; }