洛谷1546 最短网络Agri-Net【最小生成树】【prim】

【内含最小生成树Prim模板】

题目https://www.luogu.org/problemnew/show/P1546

题意:给定一个邻接矩阵。求最小生成树。

思路:点少边多用Prim。

Prim其实是把已经在最小生成树里的节点缩成一个,用priorityqueue每次找到距离当前最小生成树距离最小的那条边,加入树中。

 1 #include<cstdio>
 2 #include<cstdlib>
 3 #include<map>
 4 #include<set>
 5 #include<cstring>
 6 #include<algorithm>
 7 #include<vector>
 8 #include<cmath> 
 9 #include<stack>
10 #include<queue>
11 #include<iostream>
12 
13 #define inf 0x3f3f3f3f
14 using namespace std;
15 typedef long long LL;
16 typedef pair<int, int> pr;
17 
18 int n;
19 const int maxn = 1005;
20 int head[maxn], tot = 0;
21 struct edge{
22     int to, nxt, w;
23 }e[maxn * maxn];
24 
25 void add(int x, int y, int w)
26 {
27     e[++tot].to = y;
28     e[tot].w = w;
29     e[tot].nxt = head[x];
30     head[x] = tot;
31 //    e[++tot].to = x;
32 //    e[tot].w = w;
33 //    e[tot].nxt = head[y];
34 //    head[y] = tot;
35 }
36 
37 int ans = 0;
38 int d[maxn];
39 bool vis[maxn];
40 int prim(int s)
41 {
42     priority_queue<pr, vector<pr>, greater<pr> >que;
43     memset(d, 0x3f, sizeof(d));
44     int num = 1;
45     vis[s] = true;
46     for(int i = head[s]; i; i = e[i].nxt){
47         if(e[i].to != 1){
48             que.push(make_pair(e[i].w, e[i].to));
49             d[e[i].to] = min(d[e[i].to], e[i].w);
50         }
51     }
52     while(!que.empty() && num != n){
53         while(!que.empty() && vis[que.top().second])que.pop();
54         if(que.empty())break;
55         int x = que.top().second;
56         vis[x] = true;
57         ans += que.top().first;que.pop();
58         num++;
59         for(int i = head[x]; i; i = e[i].nxt){
60             if(!vis[e[i].to] && d[e[i].to] > e[i].w){
61                 que.push(make_pair(e[i].w, e[i].to));
62                 d[e[i].to] = e[i].w;
63             }
64         }
65     }
66     if(num != n)return -1;
67     else return ans;
68 }
69  
70 int main()
71 {
72     scanf("%d", &n);
73     for(int i = 1; i <= n; i++){
74         for(int j = 1; j <= n; j++){
75             int w;
76             scanf("%d", &w);
77             if(i != j){
78                 add(i, j, w);
79             }
80         }
81     }
82     printf("%d\n", prim(1));
83 }

 

转载于:https://www.cnblogs.com/wyboooo/p/11095968.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值