两道Prim解法范例题型,简单的裸Prim,且两题相较以边为重心的Kruskal解法而言更适合以点为重心扩展的Prim解法。
ZOJ1586-QS Network
题意:见Code
题解:直接的MST题型,本题的图为稠密图,因此适合以点为扩展导向的Prim算法(代码量也较少)。
大抵是先以某点A为中心,标记点A,访问其邻接点,更新全图到该点的距离(不通路以INF表示),找出最短距离的点B
标记最短距离的B点,然后访问其邻接点,更新邻接点到B点的最短距离,找出最短距离的点C…以此类推…
将已标记的点作为生成树M节点,此时M就是所求最小生成树。
该算法的实际核心可以理解为每次更新所有未加入生成树M的点到集合M(将M理解为一个整体)的最短距离。
因此该算法普遍将该最短距离简化为一个数组,教材上一般命名为lowcost[MAX],不断更新此数组的最小值即可。
1 //Prim-裸 2 //建立QS网络,一条网线需要一定成本及两点处的适配器成本,求最小费用 3 //本题的边数可到10^6,而点只到10^3,因此理论上说用prim比Kruskal明智(也比较好写) 4 //Time:30Ms Memory:4228K 5 #include<iostream> 6 #include<cstring> 7 #include<cstdio> 8 #include<algorithm> 9 using namespace std; 10 11 #define INF 0x3f3f3f3f 12 #define MAX 1005 13 14 int n; 15 int d[MAX][MAX]; 16 int adapter[MAX]; //适配器价格 17 int lowcost[MAX]; //各点到已生成集合的最小路长 18 bool v[MAX]; //已访问的点 19 20 void prim() 21 { 22 memset(lowcost, INF, sizeof(lowcost)); 23 memset(v, false, sizeof(v)); 24 25 int minv = 0; 26 v[0] = true; 27 for (int i = 1; i < n; i++) 28 lowcost[i] = d[i][0]; 29 for (int i = 1; i < n; i++) 30 { 31 int mind = INF; 32 int k; //最近的结点编号 33 for (int j = 0; j < n; j++) 34 { 35 if (!v[j] && mind > lowcost[j]) 36 { 37 mind = lowcost[j]; 38 k = j; 39 } 40 } 41 42 minv += mind; 43 v[k] = true; 44 for (int j = 0; j < n; j++) 45 if(!v[j]) lowcost[j] = min(lowcost[j], d[k][j]); 46 } 47 printf("%d\n", minv); 48 } 49 50 int main() 51 { 52 int T; 53 scanf("%d", &T); 54 while (T--) 55 { 56 scanf("%d", &n); 57 for (int i = 0; i < n; i++) 58 scanf("%d", &adapter[i]); 59 for (int i = 0; i < n; i++) 60 for (int j = 0; j < n; j++) 61 { 62 scanf("%d", &d[i][j]); 63 d[i][j] += adapter[i] + adapter[j]; 64 } 65 prim(); 66 } 67 return 0; 68 }
POJ1789(ZOJ2158)-Truck History
题意:由7位编码组成的卡车编码,两个编码间的距离以对应位置的编码不同个数为总距离,例如aaaaaaa,abaabaa两个编码距离为2,求使得所有卡车编码最近的距离。(与实际题意有一点不同,为了方便理解稍微改编了一些)
题解:理解了题意就好做了,本质依然是求一个裸的MST。
Prim算法思路参照上题题解。
1 //Prim-裸 2 //POJ1789-ZOJ2158 3 //边数4*10^6,点2000,稠密图较适合Prim 4 //Time:657Ms Memory:15872K 5 #include<iostream> 6 #include<cstring> 7 #include<cstdio> 8 #include<algorithm> 9 using namespace std; 10 11 #define INF 0x3f3f3f3f 12 #define MAX 2001 13 14 int n; 15 int d[MAX][MAX]; 16 int lowcost[MAX]; 17 bool v[MAX]; 18 char s[MAX][8]; 19 20 void prim() 21 { 22 memset(lowcost, INF, sizeof(lowcost)); 23 memset(v, false, sizeof(v)); 24 int minv = 0; 25 v[0] = true; 26 for (int i = 0; i < n; i++) 27 lowcost[i] = d[i][0]; 28 for (int i = 1; i < n; i++) 29 { 30 int mind = INF; 31 int k; 32 for (int j = 0; j < n; j++) 33 { 34 if (!v[j] && mind > lowcost[j]) 35 { 36 mind = lowcost[j]; 37 k = j; 38 } 39 } 40 minv += mind; 41 v[k] = true; 42 for (int j = 0; j < n; j++) 43 if (!v[j]) lowcost[j] = min(lowcost[j], d[k][j]); 44 } 45 printf("The highest possible quality is 1/%d.\n", minv); 46 } 47 48 int main() 49 { 50 while (scanf("%d", &n), n) 51 { 52 for (int i = 0; i < n; i++) 53 scanf("%s", s[i]); 54 memset(d, 0, sizeof(d)); 55 for (int i = 0; i < n; i++) 56 for (int j = i+1; j < n; j++) 57 for (int k = 0; k < 7; k++) 58 d[j][i] = d[i][j] += s[i][k] != s[j][k]; 59 prim(); 60 } 61 return 0; 62 }