• 7-38 最小生成树的唯一性


    给定一个带权无向图,如果是连通图,则至少存在一棵最小生成树,有时最小生成树并不唯一。本题就要求你计算最小生成树的总权重,并且判断其是否唯一。

    输入格式:

    首先第一行给出两个整数:无向图中顶点数 N(≤500)和边数 M。随后 M 行,每行给出一条边的两个端点和权重,格式为“顶点1 顶点2 权重”,其中顶点从 1 到N 编号,权重为正整数。题目保证最小生成树的总权重不会超过 230。

    输出格式:

    如果存在最小生成树,首先在第一行输出其总权重,第二行输出“Yes”,如果此树唯一,否则输出“No”。如果树不存在,则首先在第一行输出“No MST”,第二行输出图的连通集个数。


    输入样例 1:

    1. 5 7
    2. 1 2 6
    3. 5 1 1
    4. 2 3 4
    5. 3 4 3
    6. 4 1 7
    7. 2 4 2
    8. 4 5 5

    输出样例 1:

    1. 11
    2. Yes

    输入样例 2:

    1. 4 5
    2. 1 2 1
    3. 2 3 1
    4. 3 4 2
    5. 4 1 2
    6. 3 1 3

    输出样例 2:

    1. 4
    2. No

    输入样例 3:

    1. 5 5
    2. 1 2 1
    3. 2 3 1
    4. 3 4 2
    5. 4 1 2
    6. 3 1 3

    输出样例 3:

    1. No MST
    2. 2

    考察 :  最小生成树的深度理解

    注意 :  无

    思路 :  

    BFS求得是否存在最小生成树

    Prim 中额外加入判断生成树是否唯一

    f 记录可选择的同长路径节点

    判断这些节点间的距离是否都大与连向他们的距离

    并且每一节点仅被已出现的一个节点连接 


    C/C++ 

    box[a] -> 节点 a '直接连接的所有通路'

    apr -> appear

    1. #include
    2. using namespace std;
    3. long road[501][501];
    4. vector<int> box[501];
    5. bool apr[501];
    6. void BFS(int now);
    7. pair<long,bool>Prim(int N);
    8. int main()
    9. {
    10. memset(road,0x6f,sizeof road);
    11. int N,M,flag=0,a,b,c;
    12. cin >> N >> M;
    13. while (M--){
    14. cin >> a >> b >> c;
    15. box[a].push_back(b);
    16. box[b].push_back(a);
    17. road[a][b] = road[b][a] = c;
    18. // cout << road[a][b] << " " << road[b][a] << endl;
    19. }
    20. for(int z=1;z<=N;z++) if(!apr[z]) {
    21. flag++;
    22. BFS(z);
    23. }
    24. if(flag>1) cout << "No MST" << endl << flag << endl;
    25. else
    26. {
    27. pair<long,bool> x = Prim(N);
    28. cout << x.first << endl << (x.second?"Yes":"No");
    29. }
    30. return 0;
    31. }
    32. void BFS(int now){
    33. if(apr[now]) return;
    34. apr[now] = true;
    35. for(int x:box[now]) BFS(x);
    36. }
    37. pair<long,bool>Prim(int N){
    38. long ed[501];
    39. memset(apr,0,sizeof apr);
    40. memset(ed,0x6f,sizeof ed);
    41. bool flag = true;
    42. long sum = ed[1] = 0,f[501],len=0;
    43. vector<int> ops;
    44. for(int z=1;z<=N;z++){
    45. int op = -1;
    46. for(int z1=1;z1<=N;z1++){
    47. if(!apr[z1]){
    48. if(op==-1 || ed[z1]0;
    49. if(op==-1 || ed[z1]<=ed[op]) f[len++] = z1;
    50. }
    51. }
    52. if(flag) {
    53. for(int z1=0;z1
    54. int num = 0;
    55. for(int z2:ops) if(road[z2][f[z1]]==ed[op] && apr[z2]) num++;
    56. if(num>1) flag = false;
    57. for(int z2=z1+1;z2
    58. if(road[f[z1]][f[z2]]<=ed[op]) flag = false;
    59. if(!flag) break;
    60. }
    61. }
    62. }
    63. apr[op] = true;
    64. ops.push_back(op);
    65. sum += ed[op];
    66. for(int z1=1;z1<=N;z1++) ed[z1] = min(ed[z1],road[op][z1]);
    67. }
    68. return {sum,flag};
    69. }

     

  • 相关阅读:
    JAVA生成图片缩略图、JAVA截取图片局部内容
    【云原生 · Kubernetes】部署高可用kube-scheduler集群
    Vue样式绑定
    dubbo中几种protocol的理解
    4.方法操作实例变量 对象的行为
    什么是正则表达式?
    「摸鱼」神器来了,Python 实现人脸监测制作神器
    Windows11下安装k8s
    Unity游戏Mod/插件制作教程01 - BepInEx的安装和使用
    20221205今天的世界发生了什么
  • 原文地址:https://blog.csdn.net/daybreak_alonely/article/details/127458970