2017-9-10"切题如切菜杯"模拟赛T4 ZZI

题目


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 }
Code
原文地址:https://www.cnblogs.com/hotwords/p/7514521.html