题目链接:https://www.luogu.com.cn/problem/P1550
将在第i号田挖一个井,可以设一个超级源点,将超级源点到第i号点的边权看成是在第i号田挖井的代价,构成一个图,求这个图的最小生成树即为答案。
注意有300个顶点,最多会有300*300条边,数组要开够。
AC代码:
1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 using namespace std; 5 const int N=500005; 6 int n,ans,f[N],tot; 7 struct node{ 8 int u,v,w; 9 }edge[N]; 10 bool cmp(node a,node b){ 11 return a.w<b.w; 12 } 13 int find(int x){ 14 if(x!=f[x]) f[x]=find(f[x]); 15 return f[x]; 16 } 17 int main(){ 18 scanf("%d",&n); 19 for(int i=1;i<=n;i++){ 20 int w; scanf("%d",&w); 21 edge[++tot].u=0; 22 edge[tot].v=i; 23 edge[tot].w=w; 24 } 25 for(int i=1;i<=n;i++) 26 for(int j=1;j<=n;j++){ 27 int w; scanf("%d",&w); 28 if(j<=i) continue; 29 edge[++tot].u=i; 30 edge[tot].v=j; 31 edge[tot].w=w; 32 } 33 for(int i=0;i<=n;i++) f[i]=i; 34 sort(edge+1,edge+tot+1,cmp); 35 for(int i=1;i<=tot;i++){ 36 int r1=find(edge[i].u); 37 int r2=find(edge[i].v); 38 if(r1!=r2){ 39 f[r1]=r2; 40 ans+=edge[i].w; 41 } 42 } 43 printf("%d",ans); 44 return 0; 45 } 46 //300*300条边