题目
YYH拿到了父亲给的钱欣喜若狂,把这些钱拿来造了n栋房子。现在他要给这些房子通电。他有两种方法:第一种是在房间里搭核电发电机发电,对于不同的房子,他需要花不同的代价Vi;,第二种是将有电的房子i的电通过电线通到没电的房子j中,这样子他需要花的代价为aij。他现在请你帮他算出他最少要花多少钱才能让所有的房子通上电。
输入格式:
第一行为一个整数 n。接下来的n行为 n 个整数vi,再接下来的n行每行n个数,第i行第j列的数表示aij。
输出格式:
一个整数,表示最小代价。
样例输入:
4
5
4
4
3
0 2 2 2
2 0 3 3
2 3 0 4
2 3 4 0
样例输出:
9
题解
把用核电发电机发电的房子看作与一个有电的0号房子相连,用最小生成树解决。(看懂了题目,就觉得其实挺水的……)
数据范围很小,直接Kruskal或者Prim都行。
代码

1 #define FileIO(a) freopen(a".in","r",stdin);freopen(a".out","w",stdout); 2 #include <stdio.h> 3 #include <string.h> 4 #include <algorithm> 5 #define N 305 6 int n,m=0,f[N]; 7 struct edge{int s,t,w;}e[99999]; 8 int find(int x) { 9 return ~f[x]?f[x]=find(f[x]):x; 10 } 11 inline bool join(int a,int b) { 12 int x=find(a),y=find(b); 13 if(x==y) return false; 14 f[x]=y;return true; 15 } 16 bool cmp(edge a,edge b) { 17 return a.w<b.w; 18 } 19 int kruskal() { 20 int cnt=n,ans=0; 21 memset(f,~0,sizeof(f)); 22 std::sort(e,e+m,cmp); 23 for(int i=0;i<m;++i) { 24 if(join(e[i].s,e[i].t)) { 25 ans+=e[i].w; 26 if(!--cnt) return ans; 27 } 28 } 29 return -1; 30 } 31 int main() { 32 FileIO("zzi"); 33 int a; 34 scanf("%d",&n); 35 for(int i=1;i<=n;++i) { 36 scanf("%d",&a); 37 e[m++]={0,i,a}; 38 } 39 for(int i=1;i<=n;++i) { 40 for(int j=1;j<=n;++j) { 41 scanf("%d",&a); 42 if(i<j) e[m++]={i,j,a}; 43 } 44 } 45 printf("%d",kruskal()); 46 return 0; 47 }