数据结构 图连通与最小生成树(上)

简介: 数据结构 图连通与最小生成树

1. DS图—最小生成树


题目描述


根据输入创建无向网。分别用Prim算法和Kruskal算法构建最小生成树。(假设:输入数据的最小生成树唯一。)


输入


顶点数n


n个顶点


边数m


m条边信息,格式为:顶点1顶点2权值


Prim算法的起点v


输出


输出最小生成树的权值之和


对两种算法,按树的生长顺序,输出边信息(Kruskal中边顶点按数组序号升序输出)


输入样例


6

v1 v2 v3 v4 v5 v6

10

v1 v2 6

v1 v3 1

v1 v4 5

v2 v3 5

v2 v5 3

v3 v4 5

v3 v5 6

v3 v6 4

v4 v6 2

v5 v6 6

v1


输出样例


15

prim:

v1 v3 1

v3 v6 4

v6 v4 2

v3 v2 5

v2 v5 3

kruskal:

v1 v3 1

v4 v6 2

v2 v5 3

v3 v6 4

v2 v3 5


参考代码

#include<iostream>
#include<cstring> 
using namespace std;
const int maxx= 100;
int n;
int array[maxx][maxx];
class Kru{//存储kruskal算法中的节点
    public:
    int bef; 
    int aft;
    int data;
    int flag;
    Kru(){
        bef= -1;
        aft= -1;
        data= 0;
        flag= 0;
    }
};
void prim(string str[], int n, int po){//prim算法
    int index= po;//开始遍历的顶点
    int sum= 0; 
    int visit[n+ 5];//记录每个顶点是否被访问
    int dist[n+ 5];//最小树的权重集合
    int pos[n+ 5]; //最小树与dist[]对应的顶点
    memset(visit, false, sizeof(visit));
     visit[index]= true;
     int bef= index;
     for(int i= 0; i< n ; i++){//初始dist集合为开始顶点的相邻点
        dist[i]= array[index][i];
        pos[i]= index* 100+ i;//表示index 与i连通,记录x坐标和y坐标
     }
     //string ss= "";
     string beff[n+ 5];//每条边的头
     string aft[n+ 5];//每条边的尾
     int quan[n+ 5];//每条边的权重
     int r= 0;
     for(int i= 1; i< n; i++){
        int minn= 10000;
        for(int j= 0; j< n; j++){
            if(!visit[j]&&dist[j]< minn){//找出dist[]中的最小的那条边
                minn= dist[j];
                index= j;
             }
         }
         visit[index]= true;
         beff[r]= str[pos[index]/100];
         aft[r]= str[index];
         quan[r++]= dist[index];
         sum+= dist[index];
         for(int j= 0; j< n; j++){
            if(!visit[j]&&dist[j]> array[index][j]){//查找下一个顶点相连的边是否还有更小的, 
                                                    //有则更新
                dist[j]= array[index][j];
                pos[j]= index* 100+ j;
             }
         }
     }
     cout<<sum<<endl<<"prim:"<<endl;
     for(int i= 0; i< r; i++){
        cout<<beff[i]<<' '<<aft[i]<<" "<<quan[i]<<endl;
     }
}
int findmin(Kru kr[], int in){//找出kr[]数组中权重最小的边
    int minn= 10000;
    int index= 0;
    int flag= 0;
     for(int i= 0; i< in; i++){
        if(!kr[i].flag&&kr[i].data< minn){//如果该边没被访问且最小
            minn= kr[i].data;
            index= i;
            flag= 1;
         }
     }
     return index;
}
int find(string str[], int n, string st){//返回st字符串的下标
    for(int i= 0; i< n; i++)
      if(str[i]== st)
        return i;
}
void change(int visit[], int n, int a, int b){//将两个顶点及与他们相通的顶点改成同样的值表示 
                                              //他们相通
    for(int i= 0; i< n; i++)
      if(visit[i]== a)
        visit[i]= b;
}
void kruskal(string str[], int in, int n, Kru kr[]){//kruskal算法
    int visit[n+ 5];
    for(int i= 0; i< n; i++)
      visit[i]= i;//初始visit[]数组
     //int k= 0;  
     cout<<"kruskal:"<<endl;
     int k= 0;
     while(true){
        int minn= findmin(kr, in);//找出权重最小的边
         kr[minn].flag= 1;
         int t1= kr[minn].bef;
         int t2= kr[minn].aft;
        if(visit[t1]!= visit[t2]){//如果两个顶点的visit值不一样说明还没相通
            if(t1> t2){
                int t= t1;
                t1= t2;
                t2= t;
             }
            cout<<str[t1]<<" "<<str[t2]<<" "<<kr[minn].data<<endl;
            change(visit, n, visit[t1], visit[t2]);//将两个顶点连通
         }
         k++;
         if(k>= in)
         break;
     } 
}
int main(){
    cin>>n;
    string str[100];
    for(int i= 0; i< n; i++)
      cin>>str[i];
    for(int i= 0; i< n; i++)
      for(int j= 0; j< n; j++)
        array[i][j]= 10000;
    int in;
    cin>>in;      
    Kru kr[in+ 5];
        for(int j= 0; j< in; j++){
            string s1; 
            string s2;
            int shu;
            cin>>s1>>s2>>shu;
            //prim
            int t1= find(str, n, s1);
            int t2= find(str, n, s2);
            array[t1][t2]= shu;
            array[t2][t1]= shu;
            //krushal
            kr[j].bef= t1;
            kr[j].aft= t2;
            kr[j].data= shu;
            kr[j].flag= 0;
        }
     string s;
     cin>>s;
     int d= find(str, n, s);
     prim(str, n, d) ; 
     kruskal(str, in, n, kr);
    return 0;
}


2. DS图—图的连通分量


题目描述


输入无向图顶点信息和边信息,创建图的邻接矩阵存储结构,计算图的连通分量个数。


输入


测试次数t


每组测试数据格式如下:


第一行:顶点数 顶点信息


第二行:边数


第三行开始,每行一条边信息


输出


每组测试数据输出,顶点信息和邻接矩阵信息


输出图的连通分量个数,具体输出格式见样例。


每组输出直接用空行分隔。


输入样例


3

4 A B C D

2

A B

A C

6 V1 V2 V3 V4 V5 V6

5

V1 V2

V1 V3

V2 V4

V5 V6

V3 V5

8 1 2 3 4 5 6 7 8

5

1 2

1 3

5 6

5 7

4 8


输出样例


A B C D

0 1 1 0

1 0 0 0

1 0 0 0

0 0 0 0

2


V1 V2 V3 V4 V5 V6

0 1 1 0 0 0

1 0 0 1 0 0

1 0 0 0 1 0

0 1 0 0 0 0

0 0 1 0 0 1

0 0 0 0 1 0

1


1 2 3 4 5 6 7 8

0 1 1 0 0 0 0 0

1 0 0 0 0 0 0 0

1 0 0 0 0 0 0 0

0 0 0 0 0 0 0 1

0 0 0 0 0 1 1 0

0 0 0 0 1 0 0 0

0 0 0 0 1 0 0 0

0 0 0 1 0 0 0 0

3


参考代码

#include<iostream>
#include<cstring>
using namespace std;
int find(string str[], string st, int n){
    for(int i= 0; i< n; i++)
      if(str[i]== st)
       return i;
}
int main(){
    int t;
    cin>>t;
    while(t--){
        int n;
        cin>>n;
        string str[200];
        for(int i= 0; i< n; i++)
           cin>>str[i];
        int array[n+ 5][n+5];
        for(int i= 0; i< n+ 5; i++)
          for(int j= 0 ; j< n+ 5; j++)
            array[i][j]= 0;
        int in;
        cin>>in;
        for(int i= 0 ; i< in; i++){
            string s1; 
            string s2;
            cin>>s1>>s2;
            int a= find(str, s1, n);
            int b= find(str, s2, n);
            array[a][b]= 1;
            array[b][a]= 1;
        }
        for(int i= 0; i< n; i++){
            cout<<str[i];
            if(i!= n- 1)
              cout<<" ";
        }
        cout<<endl;
        for(int i= 0; i< n; i++){
          for(int j= 0; j< n; j++){
            cout<<array[i][j];    
            if(j!= n- 1)
             cout<<" ";       
          }
            cout<<endl;
        }
        int arr[n+ 5];
        for(int i= 0; i< n+ 5; i++)
          arr[i]= i;
          for(int i= 0; i< n; i++){
            for(int j= 0; j< n ;j++){
                if(array[i][j]){
                    for(int k= 0; k< n;k++)
                      if(arr[k]== arr[i])
                        arr[k]= arr[j];
                  }
              }
          }
//      for(int i= 0; i< n; i++){
//          cout<<arr[i]<<"--";
//      }
//      cout<<endl;
        int shu[n+ 5];
        for(int i= 0; i< n ;i++)
          shu[i]= 0;
        for(int i= 0; i< n+ 5; i++)
          shu[arr[i]]++;
        int sum= 0;
        for(int i= 0; i< n; i++){
            if(shu[i])
             sum++;
        }
        cout<<sum<<endl<<endl;
        }
    return 0;
}


相关文章
|
6月前
|
存储 算法
数据结构===图
数据结构===图
|
5月前
|
算法 Python
逆袭之路!用 Python 玩转图的 DFS 与 BFS,让数据结构难题无处遁形
【7月更文挑战第12天】图的遍历利器:DFS 和 BFS。Python 中,图可表示为邻接表或矩阵。DFS 沿路径深入,回溯时遍历所有可达顶点,适合找路径和环。BFS 层次遍历,先近后远,解决最短路径问题。两者在迷宫、网络路由等场景各显神通。通过练习,掌握这些算法,图处理将游刃有余。
67 3
|
5月前
|
存储 算法 Python
“解锁Python高级数据结构新姿势:图的表示与遍历,让你的算法思维跃升新高度
【7月更文挑战第13天】Python中的图数据结构用于表示复杂关系,通过节点和边连接。常见的表示方法是邻接矩阵(适合稠密图)和邻接表(适合稀疏图)。图遍历包括DFS(深度优先搜索)和BFS(广度优先搜索):DFS深入探索分支,BFS逐层访问邻居。掌握这些技巧对优化算法和解决实际问题至关重要。**
52 1
|
6月前
|
算法 Java
Java数据结构与算法:贪心算法之最小生成树
Java数据结构与算法:贪心算法之最小生成树
|
6月前
|
算法 C语言
数据结构与算法——最小生成树问题(什么是最小生成树、Prim算法、Kruskal算法)
数据结构与算法——最小生成树问题(什么是最小生成树、Prim算法、Kruskal算法)
40 0
|
6月前
|
存储
数据结构学习记录——如何建立图(邻接矩阵、邻接表-图节点的结构、创建并初始化、插入变、完整图的建立)
数据结构学习记录——如何建立图(邻接矩阵、邻接表-图节点的结构、创建并初始化、插入变、完整图的建立)
100 0
|
6月前
|
存储 算法
数据结构学习记录——图应用实例-六度空间(题目描述、算法思路、伪代码及解读、图解)
数据结构学习记录——图应用实例-六度空间(题目描述、算法思路、伪代码及解读、图解)
72 0
|
6月前
|
存储 算法 安全
数据结构学习记录——图应用实例-拯救007(问题描述、解题思路、伪代码解读、C语言算法实现)
数据结构学习记录——图应用实例-拯救007(问题描述、解题思路、伪代码解读、C语言算法实现)
49 0
|
6月前
|
存储 C语言
数据结构学习记录——图的遍历(深度优先搜索、广度优先搜索、为什么需要两种遍历、图不连通怎么办)
数据结构学习记录——图的遍历(深度优先搜索、广度优先搜索、为什么需要两种遍历、图不连通怎么办)
75 0
|
6月前
|
存储 机器学习/深度学习
数据结构学习记录——什么是图(抽象数据类型定义、常见术语、邻接矩阵表示法、邻接表表示法)
数据结构学习记录——什么是图(抽象数据类型定义、常见术语、邻接矩阵表示法、邻接表表示法)
79 0