B. 【例题2】新的开始
题目
思路
最小生成树,先将每个点与0号点相连,边权为建立发电站的费用,然后用kruska,将边按权值从小到大排序,然后用并查集判断一边的两端点是否在同一棵树中,如果不在,则将此边加进最小生成树中。
代码
#include<bits/stdc++.h>
using namespace std;
int fa[100001],ans,n,m,t;
struct node
{
int u,v,c;
}a[100001];
bool cmp(node x,node y)
{
return x.c<y.c;
}
int find(int x)
{
if(fa[x]!=x) return fa[x]=find(fa[x]);
return x;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;++i)
{
scanf("%d",&a[i].c);
a[i].u=0;//将每个点与0号点相连
a[i].v=i;
}
int l=n;
for(int i=1;i<=n;++i)
{
for(int j=1;j<=n;++j)
{
scanf("%d",&t);
if(i<j)
{
a[++l].c=t;
a[l].u=i;
a[l].v=j;
}
}
}
for(int i=1;i<=n;++i)
{
fa[i]=i;
}
sort(a+1,a+1+l,cmp);
for(int i=1;i<=l;++i)
{
int x=find(a[i].u),y=find(a[i].v);
if(x!=y)
{
fa[x]=y;
ans+=a[i].c;
}
}
cout<<ans;
}