普里姆算法(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 }
题意:点是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 }
题意:求最小生成树的最大边权;(英语实在太烂)
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 }
简单模板题,同上;
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 }
题意:求最小生成树;
思路:prim + BFS
这题的难点在于寻找邻接矩阵;
用BFS 找到各点间的最小距离的点;
然后就是套模板;