百 花 数橘结构 9

问题 A: 将邻接矩阵存储的图转换为邻接表存储的图,附加代码模式

要求将邻接矩阵存储的图,改造为邻接表存储的图,并输出。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
 
#define MAX_SIZE 100
 
// 邻接矩阵存储的图
struct Graph{
    int vexNumber;
    string info[MAX_SIZE];
    int adjMatrix[MAX_SIZE][MAX_SIZE];
};
 
// 弧结点定义
struct ArcNode
{
    int weight; // 弧上的信息部分
    int adj;        // 邻接点的序号
    ArcNode *nextarc;
};
 
// 顶点结点定义 
struct VexNode
{
    string Info;        // 顶点上的信息部分
    ArcNode *firstarc;  // 弧链头指针
};
 
// 邻接表结构的图的定义
struct linkGraph
{
    VexNode *vexes;
    int vexnumber;
};
 
int InitGraph(linkGraph &G, int vexnumber)
{
    G.vexes = new VexNode[vexnumber];
    G.vexnumber = vexnumber;
    for (int i = 0; i < vexnumber; i++)
        G.vexes[i].firstarc = NULL;
    return 0;
}
int t;
// 将邻接矩阵存储的图转换为邻接表存储的图
void InitGraph(linkGraph &G, const Graph& g){
    InitGraph(G,g.vexNumber);
    for(int i=0;i<g.vexNumber;i++){
        for(int j=0;j<=g.vexNumber;j++){
            if(g.adjMatrix[i][j]){
                ArcNode *p=new ArcNode;
                p->adj=j;
                p->weight=g.adjMatrix[i][j];
                p->nextarc=G.vexes[i].firstarc;
                G.vexes[i].firstarc=p;
            }
        }
    }
    G.vexnumber=g.vexNumber;
}
 
int DestroyGraph(linkGraph &G)
{
    for (int i = 0; i < G.vexnumber; i++)
    {
        while (G.vexes[i].firstarc != NULL)
        {
            ArcNode *p = G.vexes[i].firstarc;
            G.vexes[i].firstarc = p->nextarc;
            delete p;
        }
    }
    delete[]G.vexes;
    G.vexes = NULL;
    G.vexnumber = 0;
    return 0;
}
 
 
// 输出邻接表存储的图
void PrintGraph(const linkGraph& G){
    ArcNode *p;
    for(int i=0;i<G.vexnumber;i++){
        p=G.vexes[i].firstarc;
        cout<<(char)('a'+i);
        while(p){
            cout<<" --> "<<(char)('a'+(p->adj));
            p=p->nextarc;
        }
        cout<<endl;
    }
}
 
/*
// please comment the following code when you submit to OJ
int main(){
    //freopen("/config/workspace/answer/test.in","r",stdin);
    //freopen("/config/workspace/answer/test.out","w",stdout);
    Graph g;
    cin >> g.vexNumber;
    for(int i=0;i<g.vexNumber;i++){
        g.info[i] = (char)('a'+i);
        for(int j=0;j<g.vexNumber;j++){
            cin >> g.adjMatrix[i][j];
        }
    }
    linkGraph G;
    InitGraph(G,g);
    PrintGraph(G);
    DestroyGraph(G);
    return 0;
}*/

问题 B: 邻接表存储的图转化为邻接矩阵存储的图-附加代码模式

以上图为例,其对应的邻接表和邻接矩阵存储方式可以分别表示为:
(1)邻接表法
节点个数:7
节点信息:a b c d e f g
a-g-f
b-c
c-e
d
e-d
f-g-e
g-d
(2)邻接矩阵法
节点个数:7
节点信息:a b c d e f g
0 0 0 0 0 1 1
0 0 1 0 0 0 0
0 0 0 0 1 0 0
0 0 0 0 0 0 0
0 0 0 1 0 0 0
0 0 0 0 1 0 1
0 1 0 1 0 0 0
请编写程序将邻接表法存储的图,转化为邻接矩阵法存储的图,并输出

没用到他的代码模式,另起炉灶。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
 
#define MAX_SIZE 100
char ch[105][105];
// 邻接矩阵存储的图
struct Graph
{
    int vexNumber;
    string vexInfo[MAX_SIZE];
    int adjMatrix[MAX_SIZE][MAX_SIZE];
};
 
// 弧结点定义
struct ArcNode
{
    int weight;       // 弧上的信息部分
    int adj;          // 邻接点的序号
    ArcNode *nextarc; // 下一条边
};
 
// 顶点结点定义
struct VexNode
{
    string Info;       // 顶点上的信息部分
    ArcNode *firstarc; // 弧链头指针
};
 
// 邻接表结构的图的定义
struct linkGraph
{
    VexNode *vexes; //  每个节点的邻接表
    int vexnumber;  //  节点数量
};
int n;
// 邻接表存储的图的初始化
int InitGraph(linkGraph &G, int vexnumber)
{
    G.vexes = new VexNode[vexnumber];
    G.vexnumber = vexnumber;
    for (int i = 0; i < vexnumber; i++)
        G.vexes[i].firstarc = NULL;
    return 0;
}
// 构造边节点指针
ArcNode* getArcNode(int adj){
    ArcNode* node = new ArcNode();
    node->adj = adj;
    node->nextarc = nullptr;
    return node;
}
// 邻接表存储的图的销毁
int DestroylinkGraph(linkGraph &G)
{
    /*for (int i = 0; i < G.vexnumber; i++)
    {
        while (G.vexes[i].firstarc != NULL)
        {
            ArcNode *p = G.vexes[i].firstarc;
            G.vexes[i].firstarc = p->nextarc;
            delete p;
        }
    }
    delete[] G.vexes;
    G.vexes = NULL;
    G.vexnumber = 0;*/
    return 0;
}
// 根据输入构造邻接表存储的图
//typedef vector<int> linkGraph;
//typedef vector<int> Graph;
int t=0;
int a[105][105]={0};
void InputlinkGraph(linkGraph& LG){
    //InitGraph(LG,LG.vexnumber);
    cin>>n;
    int m=n;
    while(m--){
        string s;
        cin>>s;
        t=0;
        char str=s[0];
        for(int i=0;i<s.length();i++){
            if(s[i]<='z'&&s[i]>='a'){
                ch[m][t++]=s[i];                
                if(i==0){
                    continue;
                } 
                //t++;
                a[(str-'a')][(s[i]-'a')]=1;
                //str=s[i];
            }
        }
    }
}
// 将邻接表存储的图转化为邻接矩阵存储的图
void linkGraph2Graph(const linkGraph& LG, Graph& G){
    /*for(int i=0;i<n;i++){
        for(int j=0;j<n;j++){
            cout<<a[i][j]<<" ";
        }
        cout<<endl;
    }*/
    return; 
}
void printGraph(Graph& G){
    for(int i=0;i<n;i++){
        for(int j=0;j<n;j++){
            cout<<a[i][j]<<" ";
        }
        cout<<endl;
    }
}
// 输出邻接矩阵
void PrintlinkGraph(const linkGraph& LG){
   for(int i=n-1;i>=0;i--){
       cout<<ch[i][0];
       for(int j=1;j<strlen(ch[i]);j++){
           cout<<" --> "<<ch[i][j];
       }
       cout<<endl;
   }
}
 
/*
 
// please comment the following code when you submit to OJ
int main(){
    // freopen("/config/workspace/answer/test.in","r",stdin);
    linkGraph LG;
    Graph G;
    InputlinkGraph(LG);
    PrintlinkGraph(LG);
    linkGraph2Graph(LG,G);
    printGraph(G);
    DestroylinkGraph(LG);
    return 0;
}
*/

问题 C: 邻接矩阵存储图的DFS

在本题中,读入一个图的邻接矩阵(即数组表示),建立图并按照以上描述中的算法遍历所有顶点,输出遍历顶点的顺序。
 

一个dfs找邻接点,一个搜索。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
 
#define MAX_SIZE 100
// 邻接矩阵存储的图
bool vis[105];
struct Graph
{
    int vexNumber;
    string vexInfo[MAX_SIZE];
    int adjMatrix[MAX_SIZE][MAX_SIZE];
};
 
// 查找v0的未被访问的邻接点
int findAdjVex(const Graph& G, int v0, int visited[]){
 
}
// 以顶点v0为起点,进行一趟DFS
void DFS(const Graph& G, int v0, int visited[]){
    // 第一步: 先访问v0,标记已访问
    
    // 第二步: 再对v0的所有未被访问的邻接点进行DFS
    
}
// 对整个图进行DFS
int t;
void dfs(const Graph& G,int u){
    cout<<u<<" ";
    for(int i=0;i<G.vexNumber;i++){
        if(G.adjMatrix[u][i]&&!vis[i]){
            vis[i]=1;
            dfs(G,i);
        }
    }
}
void DFS(const Graph& G){
    // 第一步:初始化visited数组
     
   for(int i=0;i<G.vexNumber;i++){
       for(int j=0;j<G.vexNumber;j++){
            if(G.adjMatrix[i][j]&&!vis[i]){
                vis[i]=1;
                dfs(G,i);
                return;
            }
        }
    }
    // 第二步:以每个未被遍历的顶点为起点,进行DFS
     
}
/*
// please comment the following code when you submit to OJ
int main(){
    // freopen("/config/workspace/answer/test.in","r",stdin);
    // freopen("/config/workspace/answer/test.out","w",stdout);
     
    Graph G;
    cin >> G.vexNumber;
    for(int i=0;i<G.vexNumber;i++){
        G.vexInfo[i] = to_string(i);
        for(int j=0;j<G.vexNumber;j++){
            cin >> G.adjMatrix[i][j];
        }
    }
    DFS(G);
    return 0;
}*/

问题 D: 邻接矩阵存储图的DFS-非递归算法

在本题中,读入一个图的邻接矩阵(即数组表示),建立图并按照以上描述中的算法遍历所有顶点,输出遍历顶点的顺序。
DFS的非递归算法实现也类似于树的先序遍历算法的非递归实现,用栈来存储节点,如果该节点“完成”了,即所有邻接点都已经被访问,那么该节点将从栈中退出。

能用就行。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
 
#define MAX_SIZE 100
#define MAX_SIZE 100
 
// 邻接矩阵存储的图
struct Graph
{
    int vexNumber;
    string vexInfo[MAX_SIZE];
    int adjMatrix[MAX_SIZE][MAX_SIZE];
};
bool vis[1005];
// 查找v0的未被访问的邻接点
int findAdjVex(const Graph& G, int v0, int visited[]){
 
}
string ch="";
string str=" ";
// 以顶点v0为起点,进行一趟DFS
void dfs(const Graph& G, int v){
    ch=ch+to_string(v)+str;
    vis[v]=1;
    for(int i=0;i<G.vexNumber;i++){
        if(G.adjMatrix[v][i]&&!vis[i]){
            vis[i]=1;
            dfs(G,i);
        }
    }
}
// 对整个图进行DFS
string DFS(const Graph& G){
    string result = "";
    for(int i=0;i<G.vexNumber;i++){
        for(int j=0;j<G.vexNumber;j++){
            if(G.adjMatrix[i][j]&&!vis[i]){
                dfs(G,i);
                return ch;
            }
        }
    }
 
    // 第一步:初始化visited数组
    
    // 第二步:以每个未被遍历的顶点为起点,进行DFS
     
    return result;
}
 
/*
// please comment the following code when you submit to OJ
int main(){
    // freopen("/config/workspace/answer/test.in","r",stdin);
    // freopen("/config/workspace/answer/test.out","w",stdout);
     
    Graph G;
    cin >> G.vexNumber;
    for(int i=0;i<G.vexNumber;i++){
        G.vexInfo[i] = to_string(i);
        for(int j=0;j<G.vexNumber;j++){
            cin >> G.adjMatrix[i][j];
        }
    }
    string str = DFS(G);
    cout << str << endl;
    return 0;
}*/

问题 E: 邻接矩阵存储图的BFS

在本题中,读入一个图的邻接矩阵(即数组表示),建立图并按照以上描述中的算法遍历所有顶点,输出遍历顶点的顺序。

配合队列使用。

#include <bits/stdc++.h>
using namespace std;
int a[1005][1005];
bool vis[1005];
int n;
void bfs(int x,int y){
   // cout<<x<<" ";
    queue<int>q;
    q.push(x);
    vis[x]=1;
    while(!q.empty()){
        int t=q.front();
        q.pop();
        //if(!vis[t]) 
        cout<<t<<" ";
        for(int i=0;i<n;i++){
            if(i==t) continue;
            if(a[t][i]&&!vis[i]){
                q.push(i);
                vis[i]=1;
            }
        }
    }
}
int main()
{
    cin>>n;
    for(int i=0;i<n;i++){
        for(int j=0;j<n;j++) cin>>a[i][j];
    }
    for(int i=0;i<n;i++){
        for(int j=0;j<n;j++){
            if(a[i][j]){
                bfs(i,j);
                return 0;
            }
        }
    }
    return 0;
}

问题 F: 案例6-1.2:邻接表存储图的广度优先遍历

题目描述

一个图有n个节点编号从0至n-1和m条边编号从0至m-1。 输出从点x开始的广度优先遍历顺序。

输入格式

第一行为n、m、x。 
接下来m行每行有一组u,v。表示点u可以到达点v,点v也可以到达点u。

输出格式

输出经过点的顺序。(输出字典序最小的答案)

#include <bits/stdc++.h>
using namespace std;
int a[1005][1005]={0};
bool vis[1005];
int n,m,x;
void bfs(int s){
   // cout<<x<<" ";
    queue<int>q;
    q.push(s);
    vis[s]=1;
    while(!q.empty()){
        int t=q.front();
        q.pop();
        //if(!vis[t]) 
        cout<<t<<" ";
        for(int i=0;i<n;i++){
            if(i==t) continue;
            if(a[t][i]&&!vis[i]){
                q.push(i);
                vis[i]=1;
            }
        }
    }
}
int main()
{
    cin>>n>>m>>x;
    for(int i=0;i<m;i++){
        int l,r;
        cin>>l>>r;
        a[l][r]=a[r][l]=1;
    }
    bfs(x);
    return 0;
}

问题 G: 邻接矩阵存储图的DFS完成序求解

请编写程序,求解一个图的深度优先遍历完成序。本题为附加代码模式

和上面的差不多。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define MAX_SIZE 100
 
// 邻接矩阵存储的图
struct Graph
{
    int vexNumber;
    string vexInfo[MAX_SIZE];
    int adjMatrix[MAX_SIZE][MAX_SIZE];
};
bool vis[1005];
// 查找v0的未被访问的邻接点
int findAdjVex(const Graph& G, int v0, int visited[]){
 
}
 
// 算法7-1: 以某个节点为起点求解DFS完成序的算法 (邻接矩阵)
string DFS_finished(const Graph &G, int v0, int visited[]){
     
}
string s;
void dfs(const Graph &G,int v){
    //vis[v]=1;
    s=G.vexInfo[v]+s;
    for(int i=0;i<G.vexNumber;i++){
        if(G.adjMatrix[v][i]&&!vis[i]){
            vis[i]=1;
            //s+=G.vexInfo[i];
            dfs(G,i);
            //vis[i]=0;
            //s+=G.vexInfo[i];
       }
    }
    //s+=G.vexInfo[v];
}
 
// 算法7: DFS完成序的求解算法-邻接矩阵
string DFS_finished(const Graph &G){
    string ch;
    for(int i=0;i<G.vexNumber;i++){
        for(int j=0;j<G.vexNumber;j++){
            if(G.adjMatrix[i][j]&&!vis[i]){
                vis[i]=1;
                s="";
                dfs(G,i);
                ch+=s;
                break;
            }
        }
    }
    return ch;
}
/*
// please comment the following code when you submit to OJ
int main(){
    // freopen("/config/workspace/answer/test.in","r",stdin);
    // freopen("/config/workspace/answer/test.out","w",stdout);
     
    Graph G;
    cin >> G.vexNumber;
    for(int i=0;i<G.vexNumber;i++){
        G.vexInfo[i] = (char)('a'+ i);
        for(int j=0;j<G.vexNumber;j++){
            cin >> G.adjMatrix[i][j];
        }
    }
    string str = DFS_finished(G);
    cout << str << endl;
    return 0;
}
*/

问题 H: 案例6-1.1:DFS应用-计算可达城市对

题目描述

共有N个城市编号1到N和M条路编号1到M。
第i条路可以从城市Ai通往Bi,但不能从Bi通往Ai。
你计划从某个城市出发经过X(X>=0)条路到某个城市,即计划从某个城市经过任意条路到另一个城市,终点可以是出发的城市。
请计算有多少对城市可以作为你的起点和终点。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int a[2005][2005]={0};
bool vis[3005];
int n,m,t=0;
int dfs(int s){
    vis[s]=1;
    //t++;
    for(int i=1;i<=n;i++){
        if(a[s][i]&&!vis[i]){
            t++;
            vis[i]=1;
            dfs(i);
        }
    }
    return t;
}
int main()
{
    cin>>n>>m;
    for(int i=0;i<m;i++){
        int l,r;
        cin>>l>>r;
        a[l][r]=1;
    }
    int sum=0;
    for(int i=1;i<=n;i++){
        memset(vis,0,sizeof(vis));
        t=0;
        sum+=dfs(i);
    }
    cout<<sum+n;
    return 0;
}

问题 I: 案例6-1.3:哥尼斯堡的“七桥问题”

现给定一个无向图,问是否存在欧拉回路?

刚学的离散数学。确认每个节点的度数是偶数。

#include <bits/stdc++.h>
using namespace std;
int a[1005]={0};
int main()
{
    int n,m;
    cin>>n>>m;
    for(int i=0;i<m;i++){
        int x,y;
        cin>>x>>y;
        a[x]++;
        a[y]++;
    }
    int k=0;
    for(int i=1;i<=n;i++) if(a[i]%2) k++;
    if((k==0&&m)||n==1) cout<<"1";
    else cout<<"0";
    return 0;
}

问题 J: 案例6-1.4:地下迷宫探索

假设有一个地下通道迷宫,它的通道都是直的,而通道所有交叉点(包括通道的端点)上都有一盏灯和一个开关。请问你如何从某个起点开始在迷宫中点亮所有的灯并回到起点?

输入格式

输入第一行给出三个正整数,分别表示地下迷宫的节点数N(1<N≤1000,表示通道所有交叉点和端点)、边数M(≤3000,表示通道数)和探索起始节点编号S(节点从1到N编号)。随后的M行对应M条边(通道),每行给出一对正整数,分别是该条边直接连通的两个节点的编号。

输出格式

若可以点亮所有节点的灯,则输出从S开始并以S结束的包含所有节点的序列,序列中相邻的节点一定有边(通道);否则虽然不能点亮所有节点的灯,但还是输出点亮部分灯的节点序列,最后输出0,此时表示迷宫不是连通图。

由于深度优先遍历的节点序列是不唯一的,为了使得输出具有唯一的结果,我们约定以节点小编号优先的次序访问(点灯)。在点亮所有可以点亮的灯后,以原路返回的方式回到起点。

多个回溯功能。

#include <bits/stdc++.h>
using namespace std;
int a[1005][1005]={0};
bool vis[3005];
int lop[3005];
int n,m,x,cnt=0;
void dfs(int s){
    //cout<<s<<" ";
    vis[s]=1;
    cnt++;
    //lop[cnt++]=s;
    for(int i=1;i<=n;i++){
        if(a[s][i]&&!vis[i]){
            //vis[i]=1;
            cout<<i<<" ";
            dfs(i);
            //vis[i]=0;
            cout<<s<<" ";
        }
    }
}
int main()
{
    cin>>n>>m>>x;
    for(int i=0;i<m;i++){
        int l,r;
        cin>>l>>r;
        a[l][r]=a[r][l]=1;
    }
    cout<<x<<" ";
    dfs(x);
     
    //for(int i=cnt-2;i>=0;i--) cout<<lop[i]<<" ";
    if(cnt!=n) 
        cout<<"0";
    return 0;
}

问题 K: 基础实验6-2.3:拯救007

设鳄鱼池是长宽为100米的方形,中心坐标为 (0, 0),且东北角坐标为 (50, 50)。池心岛是以 (0, 0) 为圆心、直径15米的圆。给定池中分布的鳄鱼的坐标、以及007一次能跳跃的最大距离,你需要告诉他是否有可能逃出生天。

#include <bits/stdc++.h>
using namespace std;
pair<int,int>a[1005];
bool vis[1005];
int num,m;
bool check(int n,int x,int y){
    return (a[n].first-x)*(a[n].first-x)+(a[n].second-y)*(a[n].second-y)<=m*m;
}
bool dfs(int n){
    queue<pair<int,int>> q;
    q.emplace(a[n].first,a[n].second);
    vis[n]=true;
    while(!q.empty()){
        int x=q.front().first,y=q.front().second;
        q.pop();
        if(x+m>=50||x-m<=-50||y-m<=-50||y+m>=50) return true;
        for(int i=0;i<num;i++){
            if(check(i,x,y)&&!vis[i]){
                vis[i]=true;
                q.emplace(a[i].first,a[i].second);
            }
        }
    }
    return false;
}
int main()
{
    cin>>num>>m;
    for(int i=0;i<num;i++) cin>>a[i].first>>a[i].second;
    a[num].first=0,a[num].second=0;
    if(dfs(num)) cout<<"Yes";
    else cout<<"No";
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值