【内含最小生成树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 }