zoukankan      html  css  js  c++  java
  • Prim算法的3个版本

    Prim:以贪心的思想求得最小生成树: 把已建成的树看成一个结点, 然后用贪心的方法每次添加距离最短的点。

    以Poj1258为例:http://poj.org/problem?id=1258

    1.朴素版本:邻接矩阵, 无任何优化, O(n^2)

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstdlib>
     4 #include <cstring>
     5 #include <algorithm>
     6 #include <cmath>
     7 using namespace std;
     8 
     9 const int maxn = 100 + 2;
    10 int map[maxn][maxn];
    11 bool vis[maxn];
    12 int dist[maxn];
    13 int n;
    14 
    15 int Prim(int x)
    16 {
    17     int ret = 0, p = 0;
    18     vis[x] = true;
    19     dist[x] = 0;
    20     
    21     for(int i = 1; i < n; i++)
    22     {
    23         for(int r = 1; r <= n; r++) 
    24             if(map[x][r])
    25                 dist[r] = min(dist[r], map[x][r]);
    26         
    27         for(int r = 1; r <= n; r++)
    28             if(!vis[r])
    29                 p = p ? (dist[p] < dist[r] ? p : r) : r;
    30 
    31         ret += dist[p];
    32         x = p, p = 0;
    33         vis[x] = true;
    34     }
    35     return ret;
    36 }
    37 
    38 int main()
    39 {
    40     //freopen("in.txt", "r", stdin);
    41     
    42     while(~scanf("%d", &n))
    43     {
    44         for(int i = 1; i <= n; i++)
    45             for(int r = 1; r <= n; r++)
    46                 scanf("%d", &map[i][r]);
    47                 
    48         memset(vis, false, sizeof(vis));
    49         memset(dist, 0x7f, sizeof(dist));
    50  
    51         printf("%d
    ", Prim(1));    
    52     }
    53 } 

    也没什么可解释的.

    2.临界矩阵, 优先队列优化(堆同), O(nlogn)

     1 #include <iostream>
     2 #include <cstring>
     3 #include <cstdlib>
     4 #include <cstdio>
     5 #include <algorithm>
     6 #include <cmath>
     7 #include <queue>
     8 using namespace std;
     9 
    10 const int maxn = 100 + 2;
    11 priority_queue< pair<int, int>, vector<pair<int, int> >, greater<pair<int, int> > > q;
    12 int map[maxn][maxn];
    13 bool vis[maxn];
    14 int dist[maxn];
    15 int n;
    16 
    17 int Prim(int x)
    18 {    
    19     memset(vis, false, sizeof(vis));
    20     memset(dist, 0x7f, sizeof(dist));
    21     int ret = 0;
    22     dist[x] = 0;
    23     
    24     while(!q.empty()) q.pop();
    25     
    26     for(int i = 1; i < n; i++)
    27     {
    28         vis[x] = true;
    29         
    30         for(int r = 1; r <= n; r++)
    31             if(dist[r] > map[x][r] && map[x][r] && !vis[r])
    32                 dist[r] = map[x][r], q.push(make_pair(dist[r], r));
    33             
    34         while(!q.empty() && vis[q.top().second]) 
    35             q.pop();    
    36         
    37         x = q.top().second;
    38         ret += dist[x];
    39     }
    40     return ret;
    41 }
    42 
    43 int main()
    44 {
    45 //    freopen("in.txt", "r", stdin);
    46     
    47     while(~scanf("%d", &n))
    48     {
    49         for(int i = 1; i <= n; i++)
    50             for(int r = 1; r <= n; r++)
    51                 scanf("%d", &map[i][r]);
    52             
    53         printf("%d
    ", Prim(1));
    54     }
    55     
    56     
    57 } 

    <1>.pair<typename, pytename> p:是一种结构体,只有两个元素,<, >两个typename 分别为两个元素的类型

    通过 p.first, p.second 分别访问第一个元素和第二个元素。

    <2>.memset(name, value, sizeof), 属于 string.h 是字符数组的填充函数, 因为字符char类型为1字节,所以填充int数组时也是按单字节填充, 初始化时若每个字节的值过大, 会出现负数(整数存储原理, 补码。)

    <3> priority_queue< pair<int, int>, vector<pair<int, int> >, greater<pair<int, int> > > q;为声明小根堆(个人感觉优先队列和堆区分不用很明显, 因为内部存储结构已经不重要), 相邻的两个相同左右尖括号要用空格隔开, 否则会组成左移右移运算符, 此程序中时对pair进行排序, 在排序时以第一个元素为关键字, 所以pair.first应该存dist, 而不是点的编号。

    <4>.补充一下。priority_queue< pair<int, int> > q; 为声明大根堆

    3.邻接表, 优先队列

     1 #include <iostream>
     2 #include <cstdlib>
     3 #include <cstdio>
     4 #include <cstring>
     5 #include <queue>
     6 using namespace std;
     7 
     8 const int maxn = 10000 + 2, maxm = 100000 + 2;
     9 #define pii pair<int, int>
    10 #define fi first
    11 #define se second
    12 #define MP make_pair
    13 
    14 priority_queue<pii, vector<pii >, greater<pii > > heap;
    15 int n, m, dist[maxn], s, t;
    16 bool vis[maxn];
    17 
    18 struct arc
    19 {
    20     int e, v;
    21     arc *next;
    22     arc(){}
    23     arc(int e, int v, arc *next) : e(e), v(v), next(next){}
    24     void *operator new(unsigned, void *p) {return p;}
    25 }*head[maxn], mem[maxm * 2], *sp = mem;
    26 
    27 inline void addarc(int x, int y, int v)
    28 {
    29     head[x] = new(sp++) arc(y, v, head[x]);
    30     head[y] = new(sp++) arc(x, v, head[y]);
    31 }
    32 
    33 int Prim(int x)
    34 {
    35     memset(dist, 0x7f, sizeof(dist)); 
    36     dist[x] = 0;
    37     int ans = 0;
    38     for (int i = 1; i < n; i++)
    39     {
    40         vis[x] = true;
    41         for (arc *p = head[x]; p; p = p -> next)
    42             if (dist[p -> e] > p -> v)
    43                 dist[p -> e] = p -> v, heap.push(MP(dist[p -> e], p -> e));
    44         
    45         while (!heap.empty() && vis[heap.top().se]) heap.pop();
    46         
    47         x = heap.top().se;
    48         ans += dist[x];
    49     }
    50     return ans;
    51 }
    52 
    53 int main()
    54 {
    55     freopen("Prim.in", "r", stdin);
    56     freopen("Prim.out", "w", stdout);
    57 
    58     scanf("%d%d", &n, &m);
    59     int a, b, c;
    60     for (int i = 1; i <= m; i++) 
    61         scanf("%d%d%d", &a, &b, &c), addarc(a, b, c);
    62     
    63     printf("%d
    ", Prim(1));
    64 
    65     return fclose(stdin), fclose(stdout), 0;    
    66 }

    1.前向星存储图,一种牺牲空间获取时间的方法,在算法竞赛中的试用比较普遍的做法。

    2.没什么好解释的了...

  • 相关阅读:
    Servlet页面跳转实现方法的区别
    谈JSP与XML的交互
    xml可以用做什么?
    Struts1.2入门知识
    做java web 开发的简单项目必须具备的知识
    Web工程师必备的18款工具
    css的四种调用方式
    jQuery Utilities
    历年考研数学常考题型考试必备
    。net思维导图
  • 原文地址:https://www.cnblogs.com/QQ-1615160629/p/6275246.html
Copyright © 2011-2022 走看看