题目描述
把水源看作一个点,用最小生成树做,很厉害了!
#include<cstdio>
#include<queue>
#include<algorithm>
#include<cstring>
using namespace std;
const int MAX=305;
int n;
struct edge
{
int u,v,weight;
}a[MAX*MAX/2];
int f[MAX];
bool cmp(edge a,edge b)
{
return a.weight<b.weight;
}
int findFather(int x)
{
if(f[x]==-1) return x;
else{//路径压缩
int tmp=findFather(f[x]);
f[x]=tmp;
return tmp;
}
}
void Union(int x,int y)
{
int f1=findFather(x);
int f2=findFather(y);
if(f1!=f2)
f[f1]=f2;
}
int main()
{
//freopen("t1.txt","r",stdin);
//freopen("t2.txt","w",stdout);
scanf("%d",&n);
int t=0;
for(int i=1;i<=n;i++){
scanf("%d",&a[t].weight);
a[t].u=0;
a[t++].v=i;
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
int x;
scanf("%d",&x);
if(i>j){
a[t].weight=x;
a[t].u=i;
a[t++].v=j;
}
}
}
memset(f,-1,sizeof(f));
sort(a,a+t,cmp);
int p,q,m=0,ans=0;
for(int i=0;i<t;i++)
{
p=findFather(a[i].u);
q=findFather(a[i].v);
if(p!=q){
ans+=a[i].weight;
Union(p,q);
m++;
}
if(m==n) break;
}
printf("%d",ans);
return 0;
}