问题 A: DS图—图的邻接矩阵存储及度计算
题目描述
假设图用邻接矩阵存储。输入图的顶点信息和边信息,完成邻接矩阵的设置,并计算各顶点的入度、出度和度,并输出图中的孤立点(度为0的顶点)
–程序要求–
若使用C++只能include一个头文件iostream;若使用C语言只能include一个头文件stdio
程序中若include多过一个头文件,不看代码,作0分处理
不允许使用第三方对象或函数实现本题的要求
输入
测试次数T,每组测试数据格式如下:
图类型 顶点数 (D—有向图,U—无向图)
顶点信息
边数
每行一条边(顶点1 顶点2)或弧(弧尾 弧头)信息
输出
每组测试数据输出如下信息(具体输出格式见样例):
图的邻接矩阵
按顶点信息输出各顶点的度(无向图)或各顶点的出度 入度 度(有向图)。孤立点的度信息不输出。
图的孤立点。若没有孤立点,不输出任何信息。
样例输入
2
D 5
V1 V2 V3 V4 V5
7
V1 V2
V1 V4
V2 V3
V3 V1
V3 V5
V4 V3
V4 V5
U 5
A B C D E
5
A B
A C
B D
D C
A D
样例输出
0 1 0 1 0
0 0 1 0 0
1 0 0 0 1
0 0 1 0 1
0 0 0 0 0
V1: 2 1 3
V2: 1 1 2
V3: 2 2 4
V4: 2 1 3
V5: 0 2 2
0 1 1 1 0
1 0 0 1 0
1 0 0 1 0
1 1 1 0 0
0 0 0 0 0
A: 3
B: 2
C: 2
D: 3
E
AC代码
#include<iostream>
using namespace std;
const int GREAT = 0;
class Map {
int VertexNum;
string* Vertex;
int** AdjMatrix;
char kind;
public:
Map() {
cin >> kind >> VertexNum;
Vertex = new string[VertexNum];
for (int i = 0; i < VertexNum; i++)
cin >> Vertex[i];
AdjMatrix = new int* [VertexNum];
for (int i = 0; i < VertexNum; i++)
{
AdjMatrix[i] = new int[VertexNum];
for (int j = 0; j < VertexNum; j++)
AdjMatrix[i][j] = GREAT;
}
int n;
cin >> n;
for (int i = 0; i < n; i++) {
string s1, s2;
cin >> s1 >> s2;
int index1, index2;
for (int j = 0; j < VertexNum; j++)
if (Vertex[j] == s1)
{
index1 = j;
break;
}
for (int j = 0; j < VertexNum; j++)
if (Vertex[j] == s2)
{
index2 = j;
break;
}
switch (kind)
{
case 'U':
AdjMatrix[index2][index1] = 1;
case 'D':
AdjMatrix[index1][index2] = 1;
default:
break;
}
}
}
void display_array() {
for (int i = 0; i < VertexNum; i++)
{
cout << AdjMatrix[i][0];
for (int j = 1; j < VertexNum; j++)
cout << " " << AdjMatrix[i][j];
cout << endl;
}
}
void display_node() {
if (kind == 'U')
{
for (int i = 0; i < VertexNum; i++)
{
int cnt = 0;
for (int j = 0; j < VertexNum; j++)
if (AdjMatrix[i][j] != GREAT)
cnt++;
if (cnt)
cout << Vertex[i] << ": " << cnt << endl;
else
cout << Vertex[i] << endl;
}
}
else if (kind == 'D')
{
for (int i = 0; i < VertexNum; i++)
{
int cnt1 = 0;
for (int j = 0; j < VertexNum; j++)
if (AdjMatrix[i][j] != GREAT)
cnt1++;
int cnt2 = 0;
for (int j = 0; j < VertexNum; j++)
if (AdjMatrix[j][i] != GREAT)
cnt2++;
if (cnt1 || cnt2)
cout << Vertex[i] << ": " << cnt1 << " " << cnt2 << " " << cnt1 + cnt2 << endl;
else
cout << Vertex[i] << endl;
}
}
}
~Map()
{
delete[]Vertex;
for (int i = 0; i < VertexNum; i++)
delete[]AdjMatrix[i];
delete[]AdjMatrix;
}
};
int main() {
int n;
cin >> n;
while (n--)
{
Map m;
m.display_array();
m.display_node();
}
return 0;
}
问题 B: 图综合练习–构建邻接表
题目描述
已知一有向图,构建该图对应的邻接表。
邻接表包含数组和单链表两种数据结构,其中每个数组元素也是单链表的头结点,数组元素包含两个属性,属性一是顶点编号info,属性二是指针域next指向与它相连的顶点信息。
单链表的每个结点也包含两个属性,属性一是顶点在数组的位置下标,属性二是指针域next指向下一个结点。
输入
第1行输入整数t,表示有t个图
第2行输入n和k,表示该图有n个顶点和k条弧。
第3行输入n个顶点。
第4行起输入k条弧的起点和终点,连续输入k行
以此类推输入下一个图
输出
输出每个图的邻接表,每行输出格式:数组下标 顶点编号-连接顶点下标-…-^,数组下标从0开始。
具体格式请参考样例数据,每行最后加入“^”表示NULL。
样例输入
1
5 7
A B C D E
A B
A D
A E
B D
C B
C E
E D
样例输出
0 A-1-3-4-^
1 B-3-^
2 C-1-4-^
3 D-^
4 E-3-^
AC代码
#include<iostream>
using namespace std;
struct Node {
int VertexNo;
int Weight;
Node* NextArc;
Node() { NextArc = NULL; }
};
class Graph {
int VertexNum;
int ArcNum;
string* Vertex;
Node* AdjList;
void insert(string v1, string v2)
{
int index1, index2;
for (int i = 0; i < VertexNum; i++)
if (Vertex[i] == v1)
{
index1 = i;
break;
}
for (int i = 0; i < VertexNum; i++)
if (Vertex[i] == v2)
{
index2 = i;
break;
}
Node* p = AdjList + index1;
while (p->NextArc)
p = p->NextArc;
Node* s = new Node;
s->VertexNo = index2;
p->NextArc = s;
}
public:
Graph() {
cin >> VertexNum >> ArcNum;
Vertex = new string[VertexNum];
AdjList = new Node[VertexNum];
for (int i = 0; i < VertexNum; i++)
cin >> Vertex[i];
for (int i = 0; i < ArcNum; i++)
{
string v1, v2;
cin >> v1 >> v2;
insert(v1, v2);
}
}
void display() {
for (int i = 0; i < VertexNum; i++)
{
cout << i << " " << Vertex[i] << "-";
Node* p = (AdjList + i)->NextArc;
while (p)
{
cout << p->VertexNo << "-";
p = p->NextArc;
}
cout << "^" << endl;
}
}
~Graph() {
delete[]Vertex;
for (int i = 0; i < VertexNum; i++) {
Node* p = (AdjList + i)->NextArc;
while (p)
{
(AdjList + i)->NextArc = p->NextArc;
delete p;
p = (AdjList + i)->NextArc;
}
}
delete[]AdjList;
}
};
int main() {
int n;
cin >> n;
while (n--)
{
Graph g;
g.display();
}
return 0;
}
问题 C: DS图遍历–深度优先搜索
题目描述
给出一个图的邻接矩阵,对图进行深度优先搜索,从顶点0开始
注意:图n个顶点编号从0到n-1
代码框架如下:
输入
第一行输入t,表示有t个测试实例
第二行输入n,表示第1个图有n个结点
第三行起,每行输入邻接矩阵的一行,以此类推输入n行
第i个结点与其他结点如果相连则为1,无连接则为0,数据之间用空格隔开
以此类推输入下一个示例
输出
每行输出一个图的深度优先搜索结果,结点编号之间用空格隔开
样例输入
2
4
0 0 1 1
0 0 1 1
1 1 0 1
1 1 1 0
5
0 0 0 1 1
0 0 1 0 0
0 1 0 1 1
1 0 1 0 0
1 0 1 0 0
样例输出
0 2 1 3
0 3 2 1 4
AC代码
#include<iostream>
using namespace std;
#include<stack>
const int GREAT = 0;
class Map {
int VertexNum;
int* Vertex;
int** AdjMatrix;
bool* visited;
public:
Map() {
cin >> VertexNum;
Vertex = new int[VertexNum];
visited = new bool[VertexNum];
for (int i = 0; i < VertexNum; i++)
{
Vertex[i] = i;
visited[i] = 0;
}
AdjMatrix = new int* [VertexNum];
for (int i = 0; i < VertexNum; i++)
{
AdjMatrix[i] = new int[VertexNum];
for (int j = 0; j < VertexNum; j++)
cin >> AdjMatrix[i][j];
}
}
void dfs() {
stack<int>s;
for (int j = 0; j < VertexNum; j++)
{
if (visited[j])
continue;
s.push(j);
while (!s.empty())
{
int cur_index = s.top();
s.pop();
if (visited[cur_index])
continue;
visited[cur_index] = 1;
cout << Vertex[cur_index] << " ";
for (int i = VertexNum - 1; i >= 0; i--)
if (AdjMatrix[cur_index][i] && !visited[i])
s.push(i);
}
}
cout << endl;
}
~Map()
{
delete[]Vertex;
for (int i = 0; i < VertexNum; i++)
delete[]AdjMatrix[i];
delete[]AdjMatrix;
}
};
int main() {
int n;
cin >> n;
while (n--)
{
Map m;
m.dfs();
}
return 0;
}
问题 D: DS图遍历–广度优先搜索
题目描述
给出一个图的邻接矩阵,对图进行深度优先搜索,从顶点0开始
注意:图n个顶点编号从0到n-1
代码框架如下:
输入
第一行输入t,表示有t个测试实例
第二行输入n,表示第1个图有n个结点
第三行起,每行输入邻接矩阵的一行,以此类推输入n行
第i个结点与其他结点如果相连则为1,无连接则为0,数据之间用空格隔开
以此类推输入下一个示例
输出
每行输出一个图的广度优先搜索结果,结点编号之间用空格隔开
样例输入
2
4
0 0 1 1
0 0 1 1
1 1 0 1
1 1 1 0
5
0 0 0 1 1
0 0 1 0 0
0 1 0 1 1
1 0 1 0 0
1 0 1 0 0
样例输出
0 2 3 1
0 3 4 2 1
AC代码
#include<iostream>
using namespace std;
#include<queue>
const int GREAT = 0;
class Map {
int VertexNum;
int* Vertex;
int** AdjMatrix;
bool* visited;
public:
Map() {
cin >> VertexNum;
Vertex = new int[VertexNum];
visited = new bool[VertexNum];
for (int i = 0; i < VertexNum; i++)
{
Vertex[i] = i;
visited[i] = 0;
}
AdjMatrix = new int* [VertexNum];
for (int i = 0; i < VertexNum; i++)
{
AdjMatrix[i] = new int[VertexNum];
for (int j = 0; j < VertexNum; j++)
cin >> AdjMatrix[i][j];
}
}
void bfs() {
queue<int>q;
for (int j = 0; j < VertexNum; j++)
{
if (visited[j])
continue;
q.push(j);
while (!q.empty())
{
int cur_index = q.front();
q.pop();
if (visited[cur_index])
continue;
visited[cur_index] = 1;
cout << Vertex[cur_index] << " ";
for (int i = 0; i < VertexNum; i++)
if (AdjMatrix[cur_index][i] && !visited[i])
q.push(i);
}
}
cout << endl;
}
~Map()
{
delete[]Vertex;
for (int i = 0; i < VertexNum; i++)
delete[]AdjMatrix[i];
delete[]AdjMatrix;
}
};
int main() {
int n;
cin >> n;
while (n--)
{
Map m;
m.bfs();
}
return 0;
}
问题 E: 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
AC代码
#include<iostream>
using namespace std;
const int GREAT = 0;
class Map {
int VertexNum;
string* Vertex;
int** AdjMatrix;
int* myset; //并查集
void set_union() {
for (int i = 0; i < VertexNum; i++)
for (int j = 0; j < VertexNum; j++)
if (AdjMatrix[i][j])
{
int root1 = find(i), root2 = find(j);
if (root1 != root2)
myset[root1] = root2;
}
}
int find(int index)
{
if (index == myset[index])
return index;
return myset[index] = find(myset[index]);
}
public:
Map() {
cin >> VertexNum;
Vertex = new string[VertexNum];
myset = new int[VertexNum];
for (int i = 0; i < VertexNum; i++)
{
cin >> Vertex[i];
myset[i] = i;
}
AdjMatrix = new int* [VertexNum];
for (int i = 0; i < VertexNum; i++)
{
AdjMatrix[i] = new int[VertexNum];
for (int j = 0; j < VertexNum; j++)
AdjMatrix[i][j] = GREAT;
}
int n;
cin >> n;
for (int i = 0; i < n; i++) {
string s1, s2;
cin >> s1 >> s2;
int index1, index2;
for (int j = 0; j < VertexNum; j++)
if (Vertex[j] == s1)
{
index1 = j;
break;
}
for (int j = 0; j < VertexNum; j++)
if (Vertex[j] == s2)
{
index2 = j;
break;
}
AdjMatrix[index1][index2] = 1;
AdjMatrix[index2][index1] = 1;
}
set_union();
}
void display_array() {
for (int i = 0; i < VertexNum; i++)
{
if (i)
cout << " ";
cout << Vertex[i];
}
cout << endl;
for (int i = 0; i < VertexNum; i++)
{
cout << AdjMatrix[i][0];
for (int j = 1; j < VertexNum; j++)
cout << " " << AdjMatrix[i][j];
cout << endl;
}
}
~Map()
{
delete[]myset;
delete[]Vertex;
for (int i = 0; i < VertexNum; i++)
delete[]AdjMatrix[i];
delete[]AdjMatrix;
}
int get_connected_components() {
int cnt = 0;
for (int i = 0; i < VertexNum; i++)
if (myset[i] == i)
cnt++;
return cnt;
}
};
int main() {
int n;
cin >> n;
while (n--)
{
Map m;
m.display_array();
cout << m.get_connected_components() << endl;
cout << endl;
}
return 0;
}
问题 F: DS图—图非0面积
题目描述
编程计算由"1"围成的下列图形的面积。面积计算方法是统计"1"所围成的闭合曲线中"0"点的数目。如图所示,在10*10的二维数组中,"1"围住了15个点,因此面积为15。
输入
测试次数t
每组测试数据格式为:
数组大小m,n
一个由0和1组成的m*n的二维数组
输出
对每个二维数组,输出符号"1"围住的"0"的个数,即围成的面积。假设一定有1组成的闭合曲线,但不唯一。
样例输入
2
10 10
0 0 0 0 0 0 0 0 0 0
0 0 0 0 1 1 1 0 0 0
0 0 0 0 1 0 0 1 0 0
0 0 0 0 0 1 0 0 1 0
0 0 1 0 0 0 1 0 1 0
0 1 0 1 0 1 0 0 1 0
0 1 0 0 1 1 0 1 1 0
0 0 1 0 0 0 0 1 0 0
0 0 0 1 1 1 1 1 0 0
0 0 0 0 0 0 0 0 0 0
5 8
0 1 1 0 0 1 1 0
1 0 1 0 1 0 0 1
0 1 0 1 0 0 1 0
0 1 0 0 1 1 1 0
0 0 0 0 0 0 0 0
样例输出
15
5
AC代码
#include<bits/stdc++.h>
using namespace std;
class Array {
int** p;
int n;
int m;
void make(int x, int y)
{
if (x < 0 || y < 0 || x >= n || y >= m || p[x][y])
return;
p[x][y] = 1;
make(x - 1, y);
make(x + 1, y);
make(x, y - 1);
make(x, y + 1);
}
public:
Array() {
cin >> n >> m;
p = new int* [n];
for (int i = 0; i < n; i++)
p[i] = new int[m];
for (int i = 0; i < n; i++)
for (int j = 0; j < m; j++)
cin >> p[i][j];
}
void display() {
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
cout << p[i][j] << " ";
cout << endl;
}
}
void make()
{
for (int i = 0; i < n; i++)
{
make(i, 0);
make(i, m - 1);
}
for (int i = 0; i < m; i++)
{
make(0, i);
make(n - 1, i);
}
}
int getCount() {
int ans = 0;
for (int i = 0; i < n; i++)
for (int j = 0; j < m; j++)
if (!p[i][j])
ans++;
return ans;
}
};
int main() {
int t;
cin >> t;
while (t--)
{
Array a;
a.make();
//a.display();
cout << a.getCount() << endl;
}
}