问题 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(附加代码模式)
在本题中,读入一个图的邻接矩阵(即数组表示),建立图并按照以上描述中的算法遍历所有顶点,输出遍历顶点的顺序。
一个找邻接点,一个搜。
#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-非递归算法(附加代码模式)
在本题中,读入一个图的邻接矩阵(即数组表示),建立图并按照以上描述中的算法遍历所有顶点,输出遍历顶点的顺序。
#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完成序求解(附加代码模式)
在对图进行深度优先遍历的过程中,如果一个节点p没有未被访问的邻接点,则将该节点p标记为“完成”状态。
请编写程序,求解一个图的深度优先遍历完成序。
倒着输出的,奇奇怪怪。
#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:地下迷宫探索
假设有一个地下通道迷宫,它的通道都是直的,而通道所有交叉点(包括通道的端点)上都有一盏灯和一个开关。请问你如何从某个起点开始在迷宫中点亮所有的灯并回到起点?
多了个回溯。
#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;
}