zoj1586 QS Network ——最小生成树入门题_Prim算法

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=586

题目大意:

  题目意思比较难懂。看书上的翻译竟然没有看懂,还是打开OJ,看英文的原题。看了两遍的样子,终于差不多懂了。

  QS是一种生物,要完成通信,需要设备,每个QS需要的设备的价格不同,并且,这种设备只能在两个QS之间用一次,也就是说,如果一个QS需要和3个QS通信的话,它就必须得买3个设备,同时,对方三个也必须买对应的适合自己的设备。同时,每两个QS之间是有距离的,要完成通信还需要网线,给出每两个QS之间的网线的价值。求一棵生成树,使得所需要的费用最少。数据范围:所有数据都在1000以内。

题目思路:

  根据这种设备的特性,每个设备只能和另外一个QS通信,所以呢,建图的时候,每条边的权值就是网线的费用,加上这条边的两个端点的QS所需设备的费用的和。这样,就转化成了常规的最小生成树的问题。因为只需要求出最小费用,所以,可以不必记录prim过程中要选的边的顶点编号,也就是说,可以省略nearvex数组,用lowcost数组就可以实现。如果lowcost[i]的值是-1,则代表已经选择了这个点,否则,lowcost[i]依然表示集合T1内的顶点 i 距离集合T内个顶点权值最小的边的权值。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstdlib>
 4 #include <cstring>
 5 #include <cctype>
 6 #include <stack>
 7 #include <queue>
 8 #include <map>
 9 #include <set>
10 #include <vector>
11 #include <cmath>
12 #include <algorithm>
13 #define lson l, m, rt<<1
14 #define rson m+1, r, rt<<1|1
15 using namespace std;
16 typedef long long int LL;
17 const int MAXN =  0x3f3f3f3f;
18 const int  MIN =  -0x3f3f3f3f;
19 const double eps = 1e-9;
20 const int dir[8][2] = {{0,1},{1,0},{0,-1},{-1,0},{-1,1},
21   {1,1},{1,-1},{-1,-1}};
22 const int MAX = 1000+10;
23 int edge[MAX][MAX], lowcost[MAX];
24 int t, n, pri[MAX];
25 void prim(int u0) 
26 {
27   int sum = 0, i, j, v;
28   for (i = 1; i <= n; ++i) lowcost[i] = edge[u0][i];
29   lowcost[u0] = -1;
30   for (i = 1; i < n; ++i) {
31     int min = MAXN; v = -1;
32     for (j = 1; j <= n; ++j) {
33       if (min > lowcost[j] && lowcost[j] != -1) {
34         v = j; min = lowcost[j];
35       }
36     }
37     if (v != -1) {
38       sum += lowcost[v]; lowcost[v] = -1;
39       for (j = 1; j <= n; ++j) {
40         if (edge[v][j] < lowcost[j] && lowcost[j] != -1) {
41           lowcost[j] = edge[v][j];
42         }
43       }
44     }
45   }
46   printf("%d\n", sum);
47 }
48 int main(void){
49 #ifndef ONLINE_JUDGE
50   freopen("zoj1568.in", "r", stdin);
51 #endif
52   scanf("%d", &t);
53   int i, j, k;
54   while (t--) {
55     memset(edge, 0, sizeof(edge));
56     scanf("%d", &n);
57     for (i = 1; i <= n; ++i) scanf("%d", &pri[i]);
58     for (i = 1; i <= n; ++i) {
59       for (j = 1; j <= n; ++j) {
60         scanf("%d", &edge[i][j]);
61         edge[i][j] += (pri[i] + pri[j]);
62       }
63     }
64     prim(1);
65   }
66 
67   return 0;
68 }

写这道题目的时候,遇到一个比较坑的问题,导致输出怎么也不出结果。。。后来才发现,读文件那句话里的文件名写错了……好吧……我去……

posted on 2013-05-03 01:59  aries__liu  阅读(582)  评论(0编辑  收藏  举报