思路
这道题我们可以设一个超级点,然后把超级点连向每个普通点,
边权就是每个普通点的权值。
最后跑一个最小生成树就好了。
代码
第一种统计法:
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
int l[310][310],dis[1000],n,minn[1000],v[1000],ans;
int main()
{
cin>>n;
for(int i=1; i<=n; i++)
scanf("%d",&dis[i]);
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++)
scanf("%d",&l[i][j]);
for(int i=1; i<=n; i++)
l[0][i]=dis[i];
memset(minn,1,sizeof(minn));
minn[0]=0;
for(int i=1; i<=n; i++)
if(l[0][i]<minn[i])
minn[i]=l[0][i];
v[0]=1;
for(int i=1; i<=n; i++)
{
int k=2147483647,p;
for(int j=0; j<=n; j++)
if(v[j]==0&&minn[j]<k)
p=j,k=min(minn[j],k);
v[p]=1;
for(int j=0; j<=n; j++)
if(l[p][j]<minn[j]&&v[j]==0)
minn[j]=l[p][j];
}
for(int i=1; i<=n; i++)
ans+=minn[i];
cout<<ans;
return 0;
}
第二种统计方法:
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
int l[310][310],dis[1000],n,minn[1000],v[1000],ans;
int main()
{
cin>>n;
for(int i=1; i<=n; i++)
scanf("%d",&dis[i]);
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++)
scanf("%d",&l[i][j]);
for(int i=1; i<=n; i++)
l[0][i]=dis[i];
memset(minn,1,sizeof(minn));
minn[0]=0;
for(int i=1; i<=n; i++)
if(l[0][i]<minn[i])
minn[i]=l[0][i];
v[0]=1;
for(int i=1; i<=n; i++)
{
int k=2147483647,p;
for(int j=0; j<=n; j++)
if(v[j]==0&&minn[j]<k)
p=j,k=min(minn[j],k);
v[p]=1;
ans+=k;
for(int j=0; j<=n; j++)
if(l[p][j]<minn[j])
minn[j]=l[p][j];
}
cout<<ans;
return 0;
}