• 无向图最小生成树(prim算法)


    普里姆算法Prim算法),图论中的一种算法,可在加权连通图里搜索最小生成树。意即由此算法搜索到的边子集所构成的树中,不但包括了连通图里的所有顶点,且其所有边的权值之和亦为最小。该算法于1930年由捷克数学家沃伊捷赫·亚尔尼克发现;并在1957年由美国计算机科学家罗伯特·普里姆独立发现;1959年,艾兹格·迪科斯彻再次发现了该算法。因此,在某些场合,普里姆算法又被称为DJP算法亚尔尼克算法普里姆-亚尔尼克算法

    算法过程图解:遍历点,用贪心法选择与集合内的点相连的点的最小值;

     模板:

     1 #include <iostream>
     2 #include <algorithm>
     3 #include <cmath>
     4 #include <cstdio>
     5 #include <string>
     6 #include <cstring>
     7 #include <vector>
     8 #include <queue>
     9 #include <stack>
    10  #include <set>
    11  #define INF 0x3f3f3f3f
    12  #define INFL 0x3f3f3f3f3f3f3f3f
    13  #define zero_(x,y) memset(x , y , sizeof(x))
    14  #define zero(x) memset(x , 0 , sizeof(x))
    15  #define MAX(x) memset(x , 0x3f ,sizeof(x))
    16  using namespace std;
    17  #define N 1005
    18  typedef long long LL ;
    19  int G[N][N];
    20  int minn[N];///寻找最小权;
    21  bool point[N];
    22 
    23  int main(){
    24      //freopen("in.txt","r",stdin);
    25      memset(point, 0, sizeof(point));
    26      int n, m, x, y, ans=0;
    27      scanf("%d%d", &n, &m);
    28      for(int i=1;i<=n;i++){
    29          for(int j = 1; j <= n; j++){
    30              G[i][j] = INF;
    31          }
    32      }
    33      for(int i = 1; i <= m; i++) {
    34          scanf("%d%d", &x, &y);
    35          scanf("%d", &G[x][y]);
    36          G[y][x] = G[x][y];
    37      }
    38      point[1] = true;
    39      for(int i = 1;i <= n; i++) minn[i] = G[1][i];
    40      for(int i = 1 ; i <= n; i++){
    41          int k = 0, mi = INF;
    42          for(int j = 1; j <= n; j++){
    43              if(!point[j] && minn[j] < mi){
    44                  mi = minn[j];
    45                  k = j;
    46              }
    47          }
    48          ans += minn[k];
    49          point[k] = true;
    50          for(int s = 1;s <= n; s++){
    51              if(!point[s] && G[k][s] < minn[s])///保存了之前没有加入集合的边的权;
    52                  minn[s] = G[k][s];
    53          }
    54      }
    55      printf("%d
    ", ans);
    56      return 0;
    57  }
    View Code

    poj 1789

    题意:点是7位小写字母,边是小写字母间的不同字母数量(1-7)。求最小生成树。

    边权:the number of positions with different letters in truck type codes.

     

     1 #include <iostream>
     2 #include <algorithm>
     3 #include <stdlib.h>
     4 #include <time.h>
     5 #include <cmath>
     6 #include <cstdio>
     7 #include <string>
     8 #include <cstring>
     9 #include <vector>
    10 #include <queue>
    11 #include <stack>
    12 #include <set>
    13 
    14 #define c_false ios_base::sync_with_stdio(false); cin.tie(0)
    15 #define INF 0x3f3f3f3f
    16 #define INFL 0x3f3f3f3f3f3f3f3f
    17 #define zero_(x,y) memset(x , y , sizeof(x))
    18 #define zero(x) memset(x , 0 , sizeof(x))
    19 #define MAX(x) memset(x , 0x3f ,sizeof(x))
    20 #define swa(x,y) {LL s;s=x;x=y;y=s;}
    21 using namespace std ;
    22 #define N 2005
    23 
    24 const double PI = acos(-1.0);
    25 typedef long long LL ;
    26 int n, dis[N][N], minn[N];
    27 char x[10];
    28 string type[N];
    29 bool point[N];
    30 
    31 int Distance(int i, int j){
    32     int len = 7, sum = 0;
    33     for(int k = 0; k < len; k++)
    34         if(type[i][k] != type[j][k])
    35             sum++;
    36     return sum;
    37 }
    38 int prim(){
    39     point[1] = true;
    40     int ans = 0;
    41     for(int i = 1; i <= n; i++) minn[i] = dis[1][i];
    42     for(int i = 1; i <= n; i++){
    43         int k = 0; int mi =INF;
    44         for(int j = 1; j <= n; j++){
    45             if(!point[j] && minn[j] <mi){
    46                 mi = minn[j];
    47                 k = j;
    48             }
    49         }
    50         ans += minn[k];
    51         point[k] = true;
    52         for(int s = 1; s <= n; s++){
    53             if(!point[s] && dis[k][s] <minn[s])
    54                 minn[s] = dis[k][s];
    55         }
    56     }
    57     return ans;
    58 }
    59 int main(){
    60     //freopen("in.txt","r",stdin);
    61     //freopen("out.txt","w",stdout);
    62     //ios_base::sync_with_stdio(false); cin.tie(0);
    63     while(~scanf("%d", &n) && n){
    64         zero(dis);zero(point);MAX(dis);
    65         for(int i = 1; i <= n; i++){
    66             scanf("%s", x);
    67             type[i] = x;
    68         }
    69         for(int i = 1; i<= n; i++){
    70             for(int j = 1; j < i; j++){
    71                 dis[i][j] = dis[j][i] = Distance(i, j);
    72             }
    73         }
    74         printf("The highest possible quality is 1/%d.
    ", prim());
    75     }
    76     return 0;
    77 }
    View Code

    poj 2485

    题意:求最小生成树的最大边权;(英语实在太烂)

     point:minimize the length of the longest highway

     1 #include <iostream>
     2 #include <algorithm>
     3 #include <stdlib.h>
     4 #include <time.h>
     5 #include <cmath>
     6 #include <cstdio>
     7 #include <string>
     8 #include <cstring>
     9 #include <vector>
    10 #include <queue>
    11 #include <stack>
    12 #include <set>
    13 
    14 #define c_false ios_base::sync_with_stdio(false); cin.tie(0)
    15 #define INF 0x3f3f3f3f
    16 #define INFL 0x3f3f3f3f3f3f3f3f
    17 #define zero_(x,y) memset(x , y , sizeof(x))
    18 #define zero(x) memset(x , 0 , sizeof(x))
    19 #define MAX(x) memset(x , 0x3f ,sizeof(x))
    20 #define swa(x,y) {LL s;s=x;x=y;y=s;}
    21 using namespace std ;
    22 #define N 505
    23 
    24 const double PI = acos(-1.0);
    25 typedef long long LL ;
    26 int T, n, dis[N][N], minn[N];
    27 bool point[N];
    28 
    29 int prim(){
    30     point[1] = true;
    31     int ans = 0;
    32     for(int i = 1; i <= n; i++) minn[i] = dis[1][i];
    33     for(int i = 1; i <= n; i++){
    34         int k = 0; int mi =INF;
    35         for(int j = 1; j <= n; j++){
    36             if(!point[j] && minn[j] <mi){
    37                 mi = minn[j];
    38                 k = j;
    39             }
    40         }
    41         if(ans < minn[k]) ans = minn[k];
    42         point[k] = true;
    43         for(int s = 1; s <= n; s++){
    44             if(!point[s] && dis[k][s] <minn[s])
    45                 minn[s] = dis[k][s];
    46         }
    47     }
    48     return ans;
    49 }
    50 
    51 int main(){
    52     //freopen("in.txt","r",stdin);
    53     //freopen("out.txt","w",stdout);
    54     //ios_base::sync_with_stdio(false); cin.tie(0);
    55     scanf("%d", &T);
    56     while(T--){
    57         zero(point);zero(dis);zero(minn);
    58         scanf("%d", &n);
    59         for(int i = 1; i <= n; i++){
    60             for(int j = 1; j <= n; j++){
    61                 scanf("%d", &dis[i][j]);
    62             }
    63         }
    64         printf("%d
    ", prim());
    65     }
    66     return 0;
    67 }
    View Code

    poj 1258

    简单模板题,同上;

     1 #include <iostream>
     2 #include <algorithm>
     3 #include <stdlib.h>
     4 #include <time.h>
     5 #include <cmath>
     6 #include <cstdio>
     7 #include <string>
     8 #include <cstring>
     9 #include <vector>
    10 #include <queue>
    11 #include <stack>
    12 #include <set>
    13 
    14 #define c_false ios_base::sync_with_stdio(false); cin.tie(0)
    15 #define INF 0x3f3f3f3f
    16 #define INFL 0x3f3f3f3f3f3f3f3f
    17 #define zero_(x,y) memset(x , y , sizeof(x))
    18 #define zero(x) memset(x , 0 , sizeof(x))
    19 #define MAX(x) memset(x , 0x3f ,sizeof(x))
    20 #define swa(x,y) {LL s;s=x;x=y;y=s;}
    21 using namespace std ;
    22 #define N 505
    23 
    24 const double PI = acos(-1.0);
    25 typedef long long LL ;
    26 int n, dis[N][N], minn[N];
    27 bool point[N];
    28 
    29 int prim(){
    30     point[1] = true;
    31     int ans = 0;
    32     zero(minn);zero(point);
    33     for(int i = 1; i <= n; i++) minn[i] = dis[1][i];
    34     for(int i = 1; i <= n; i++){
    35         int k = 0; int mi =INF;
    36         for(int j = 1; j <= n; j++){
    37             if(!point[j] && minn[j] <mi){
    38                 mi = minn[j];
    39                 k = j;
    40             }
    41         }
    42         ans += minn[k];
    43         point[k] = true;
    44         for(int s = 1; s <= n; s++){
    45             if(!point[s] && dis[k][s] <minn[s])
    46                 minn[s] = dis[k][s];
    47         }
    48     }
    49     return ans;
    50 }
    51 
    52 int main(){
    53     //freopen("in.txt","r",stdin);
    54     //freopen("out.txt","w",stdout);
    55     //ios_base::sync_with_stdio(false); cin.tie(0);
    56     while(~scanf("%d", &n) && n){
    57         zero(dis);
    58         for(int i = 1; i <= n; i++){
    59             for(int j = 1; j <= n; j++){
    60                 scanf("%d", &dis[i][j]);
    61             }
    62         }
    63         printf("%d
    ", prim());
    64     }
    65     return 0;
    66 }
    View Code

    poj 3026

    题意:求最小生成树;

    思路:prim + BFS

       这题的难点在于寻找邻接矩阵;

        用BFS 找到各点间的最小距离的点;

          然后就是套模板;

  • 相关阅读:
    【SQLite】教程04-SQLite数据类型
    【SQLite】教程03-SQLite语法
    【SQLite】教程02-SQLite命令
    [原创]java WEB学习笔记22:MVC案例完整实践(part 3)---多个请求对应一个Servlet解析
    [原创]java WEB学习笔记21:MVC案例完整实践(part 2)---DAO层设计
    [原创]java WEB学习笔记20:MVC案例完整实践(part 1)---MVC架构分析
    [转]Mysql命令
    [原创]java WEB学习笔记19:初识MVC 设计模式:查询,删除 练习(理解思想),小结 ,问题
    [原创]java WEB学习笔记18:java EE 中的MVC 设计模式(理论)
    [原创]java WEB学习笔记17:关于中文乱码的问题 和 tomcat在eclipse中起动成功,主页却打不开
  • 原文地址:https://www.cnblogs.com/yoyo-sincerely/p/5191410.html
Copyright © 2020-2023  润新知