[关闭]
@lunar 2016-04-12T20:24:08.000000Z 字数 1812 阅读 1376

HiHo一下 最小生成树 Week26 Week27

HiHo


描述

这两周练习的是最小生成树的算法,一个是基于点的Prim算法,另一个是基于边的Kruscal算法。

思路

对于Prim算法,我们将点集划分为两个子集,其中那个一个初始为空,称为已处理集,另一个初始化为全集,称为未处理集。我们将任意一个点加入到已处理集,并找出连接两个集合中点的最短边,换言之,我们要找的边的一头在已处理集,一头在未处理集,这种边可能有很多条,我们感兴趣的是权值最小的那条。找到这条边后将其加入生成树,并把边连接的未处理集中的点移出到已处理集。不断反复以上操作直到完成n-1条边的寻找也就是完成生成树的构造。
对于Kruscal算法。我们会用到并查集,一开始将所有边按权值排序,n个点分别在n个集合。取出权值最小的边,如果边两头的点不在同一集合,那就将该边加入生成树,并将两个集合合并,如果在同一集合那就继续取边。如此操作直到完成树的构造。
Prim算法复杂度为
Kruscal复杂度为

代码

  1. #include<iostream>
  2. #include<queue>
  3. using namespace std;
  4. #define MAX 1005
  5. struct edge{
  6. int x;
  7. int y;
  8. int length;
  9. bool operator < (const edge &a) const{
  10. return a.length < length;
  11. }
  12. };
  13. int map[MAX][MAX];
  14. std::vector<int> flag(MAX+1,false);
  15. std::priority_queue <edge> tree;
  16. int main(){
  17. int n;
  18. int sum = 0;
  19. cin >> n;
  20. for(int i=1;i<=n;i++){
  21. for(int j=1;j<=n;j++)
  22. cin >> map[i][j];
  23. }
  24. flag[1] = true;
  25. int t = 1;
  26. for(int i=1;i<n;i++){
  27. for(int j=1;j<=n;j++){
  28. if(t!=j&&!flag[j]){
  29. edge temp;
  30. temp.length=map[t][j];
  31. temp.x = t;
  32. temp.y = j;
  33. tree.push(temp);
  34. }
  35. }
  36. while((flag[tree.top().x] xor flag[tree.top().y])==0) tree.pop();
  37. if(flag[tree.top().x]) t = tree.top().y;
  38. else t = tree.top().x;
  39. sum += tree.top().length;
  40. flag[t] = true;
  41. tree.pop();
  42. }
  43. cout << sum;
  44. return 0;
  45. }
  1. #include<iostream>
  2. #include<queue>
  3. using namespace std;
  4. #define MAX 100005
  5. int flag[MAX];
  6. struct edge{
  7. int x;
  8. int y;
  9. int length;
  10. bool operator < (const edge &a) const{
  11. return a.length < length;
  12. }
  13. };
  14. int seekFa(int i){
  15. if (flag[i]!=i) flag[i] = seekFa(flag[i]);
  16. return flag[i];
  17. }
  18. void unionFa(int x,int y){
  19. int aa = seekFa(x);
  20. int bb = seekFa(y);
  21. if(aa>bb) flag[aa] = bb;
  22. else flag[bb] = aa;
  23. }
  24. std::priority_queue <edge> tree;
  25. int main(){
  26. int n,m;
  27. int sum = 0;
  28. cin >> n >>m;
  29. for(int i=1;i<=n;i++){
  30. flag[i] = i;
  31. }
  32. while(m--){
  33. int a, b ,c;
  34. cin >>a >> b >> c;
  35. edge temp;
  36. temp.x = a;
  37. temp.y = b;
  38. temp.length = c;
  39. tree.push(temp);
  40. }
  41. for(int i=1;i<n;i++){
  42. while((seekFa(tree.top().x))==(seekFa(tree.top().y)))
  43. tree.pop();
  44. sum +=tree.top().length;
  45. unionFa(flag[tree.top().x],flag[tree.top().y]);
  46. tree.pop();
  47. }
  48. cout << sum;
  49. return 0;
  50. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注