全连通图求最小生成树边权之积(邻接矩阵/prim/kruskal)

Description

大家都知道最小生成树一般求的是构成最小生成树的边的权值之和。
现在请求构成最小生成树的边的权值之积 S,最终结果请输出 (S % 100003)。
P.S. 点之间的边为无向边,矩阵保证符合无向图的对称性。

Input

多组数据。

第一行,整数N,表示N个点。(0 < N <= 100)

接下来为一个N*N 保证合法的邻接矩阵,矩阵内均为自然数。

Output

每组数据输出一行整数结果。

Sample Input

3
0 1 2
1 0 3
2 3 0
2
0 5
5 0

Prim

 1 #include<iostream>
 2 #include<cstring>
 3 using namespace std;
 4 
 5 #define MAX 105
 6 #define INF 0x7FFFFFFF
 7 int map[MAX][MAX];  // adjacency matrix
 8 bool vis[MAX];  // is the node i visited
 9 int dis[MAX];  // distance between current node and other node i
10 
11 void prim(int n) {
12     memset(vis, false, sizeof(vis));
13 
14     // current node is 0
15     int cur = 0;
16     for (int i = 0; i < n; ++i)
17         dis[i] = map[cur][i];  // dis[] store distance between other nodes and 0
18     vis[cur] = true;
19 
20     unsigned long long s = 1;
21     for (int i = 0; i < n - 1; ++i) {
22         // find the shortest edge between cur and other unvisited nodes
23         int min = INF;
24         for(int j = 0; j < n; ++j)
25             if (!vis[j] && dis[j] < min)
26                 min = dis[cur = j];  // update to next shortest edge and potential cur
27 
28         // the other end is visited and is now current node
29         s *= min;
30         s %= 100003;
31         vis[cur] = true;
32 
33         // update dis[] to store distance between other nodes and cur
34         // if the node is visited, leave it
35         for (int j = 0; j < n; ++j)
36             if (!vis[j] && map[cur][j] < dis[j])
37                 dis[j] = map[cur][j];
38     }
39     cout << (s % 100003) << endl;
40 }
41 
42 int main() {
43     int n;
44 
45     while(scanf("%d", &n) != EOF) {
46         for (int i = 0; i < n; ++i)
47             for (int j = 0; j < n; ++j)
48                 scanf("%d", &map[i][j]);
49         prim(n);
50     }
51 
52     return 0;
53 }

 

Kruskal,其实改装成了边表,加了并查集,有做路径压缩,可以水过就懒得写带rank的优化了……

 1 #include <iostream>
 2 #include <cstring>
 3 #include <algorithm>
 4 using namespace std;
 5 
 6 #define MAX 105
 7 #define INF 0x7FFFFFFF
 8 
 9 int root[MAX];
10 int map[MAX][MAX];
11 
12 struct Edge {
13     int u, v;
14     int d;
15 } e[MAX*MAX];
16 
17 bool cmp(Edge a, Edge b) {
18     return a.d < b.d;
19 }
20 
21 int find(int x) {
22     while(x != root[x]) {
23          root[x] = root[root[x]];  // compress
24         x = root[x];
25     }
26     return x;
27 }
28 
29 unsigned long long kruskal(int vn, int en) {
30     unsigned long long p = 1;
31 
32     // connect to itself
33     for (int i = 0; i < vn; ++i)
34         root[i] = i;
35 
36     // sort edges by length
37     std::sort(e, e+en, cmp);
38 
39     for(int i = 0; i < en; ++i) {
40         int ru = find(e[i].u);
41         int rv = find(e[i].v);
42         if(ru != rv) {  // the ends of e[i] are not in the same spanning tree
43             root[ru] = rv;  // merge
44             p *= e[i].d;
45             p %= 100003;
46         }
47     }
48 
49     return p;
50 }
51 
52 int main() {
53     int vn;
54     while(cin >> vn) {
55         memset(map, 0, sizeof(map));
56         for(int i = 0; i < vn; ++i)
57             for(int j = 0; j < vn; ++j)
58                 cin >> map[i][j];
59 
60         int en = 0;
61         for(int i = 0; i < vn; ++i)  // use upper-right corner
62             for(int j = i + 1; j < vn; ++j) {
63                 // transform to adjacency list
64                 e[en].u = i;
65                 e[en].v = j;
66                 e[en].d = map[i][j];
67                 ++en;
68             }
69            cout << kruskal(vn, en) % 100003 << '\n';
70     }
71     return 0;
72 }

 

因为数据太大所以每次乘完都要取模,不然会溢出。

因为本来就给的是邻接矩阵,kruskal要多做一步处理转换成边表,速度大约是prim的一半

转载于:https://www.cnblogs.com/joyeecheung/p/3505292.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值