2015-01-04 14:19:46

学习是螺旋性的,今天来复习一下最小生成树的prim和kruskal,及prim堆优化。

采用 POJ 1258 作为测试平台。(题意:输入N,并输入N×N的点距离邻接矩阵,输入MST总长度)

First:Prim(适合稠密图,复杂度:朴素:O(V*V);堆优化:O(E*logV)(关于这个复杂度还没怎么想明白orz...))

  思路回顾:prim是从一个只包含一个点的点集出发,不断找出从当前点集到其余点的最小权边,并添加最小权边的终点进点集,直至点集包含所有点。(可以看做点集扩张)

  简证:如果在选当前点集X的出边时不选择最小权边(假设为e),而选择另一条边(假设为f)并构成生成树T,也就是说连接X和V-X的是边f,那么如果我们把e加入T,必定构成圈,再把f删掉,此时T-f+e仍然为生成树,又因为cost(f) >= cost(e),所以T-f+e <= T,所以选择e更合算,得证。

(1)朴素prim:

  细节:总共找n-1条边,到各个点的距离用dis[]数组维护,已入点集的用used[]数组标记

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cstdlib>
 4 #include <cmath>
 5 #include <vector>
 6 #include <map>
 7 #include <set>
 8 #include <stack>
 9 #include <queue>
10 #include <iostream>
11 #include <algorithm>
12 using namespace std;
13 #define lp (p << 1)
14 #define rp (p << 1|1)
15 #define getmid(l,r) (l + (r - l) / 2)
16 #define MP(a,b) make_pair(a,b)
17 typedef long long ll;
18 typedef unsigned long long ull;
19 typedef pair<int,int> pii;
20 const int INF = (1 << 30) - 1;
21 const int maxn = 110;
22 
23 int N;
24 struct edge{
25     int v,cost;
26 }e[maxn * maxn];
27 int first[maxn],next[maxn * maxn],ecnt;
28 int dis[maxn],used[maxn];
29 
30 void Add_edge(int u,int v,int c){
31     next[++ecnt] = first[u];
32     e[ecnt].v = v;
33     e[ecnt].cost = c;
34     first[u] = ecnt;
35 }
36 
37 int Prim(){
38     int p = 1,mst = 0;
39     memset(used,0,sizeof(used));
40     fill(dis + 1,dis + N + 1,INF);
41     used[1] = 1;
42     for(int i = first[1]; i != -1; i = next[i]){
43         dis[e[i].v] = e[i].cost;
44     }
45     for(int k = 1; k < N; ++k){
46         int tmin = INF;
47         for(int i = 1; i <= N; ++i)
48             if(!used[i] && dis[i] < tmin) tmin = dis[p = i];
49         mst += tmin;
50         used[p] = 1;
51         for(int i = first[p]; i != -1; i = next[i]){
52             int v = e[i].v;
53             if(!used[v] && dis[v] > e[i].cost)
54                 dis[v] = e[i].cost;
55         }
56     }
57     return mst;
58 }
59 
60 int main(){
61     int tmp;
62     while(scanf("%d",&N) != EOF){
63         memset(first,-1,sizeof(first));
64         ecnt = 0;
65         for(int i = 1; i <= N; ++i){
66             for(int j = 1; j <= N; ++j){
67                 scanf("%d",&tmp);
68                 if(tmp) Add_edge(i,j,tmp);
69             }
70         }
71         printf("%d\n",Prim());
72     }
73     return 0;
74 }
View Code

相关文章:

  • 2022-01-06
  • 2021-11-25
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2021-11-08
  • 2021-11-13
猜你喜欢
  • 2022-12-23
  • 2022-12-23
  • 2021-06-11
  • 2022-12-23
  • 2021-12-27
  • 2022-01-18
  • 2021-10-30
相关资源
相似解决方案