Vj数据结构实验十二
描述
创建无向图类,存储结构使用邻接链表,提供操作:插入一条边,删除一条边,BFS,DFS。
格式
输入
第一行四个整数n,m,s,t。n (10 \leq n \leq 10000010≤n≤100000) 代表图中点的个数,m (10 \leq m \leq 20000010≤m≤200000) 代表接下来共有m个操作,s代表起始点,t代表终点。
接下来m行,每行代表一次插入或删除边的操作,操作格式为:
0 u v
在点u和v之间增加一条边1 u v
删除点u和v之间的边
输出
第一行输出图中有多少个连通分量
第二行输出所有连通子图中最小点的编号(升序),编号间用空格分隔
第三行输出从s点开始的dfs序列长度
第四行输出从s点开始的字典序最小的dfs序列
第五行输出从t点开始的bfs序列的长度
第六行输出从t点开始字典序最小的bfs序列
第七行输出从s点到t点的最短路径,若是不存在路径则输出-1
样例
输入
10 20 4 5
0 6 4
0 10 3
0 4 8
0 4 10
1 4 10
0 2 1
0 5 8
0 5 2
0 10 7
0 9 6
0 9 1
0 7 1
0 8 10
0 7 5
0 8 3
0 6 7
1 6 4
1 8 3
0 7 8
0 9 2
输出
1
1
10
4 8 5 2 1 7 6 9 10 3
10
5 2 7 8 1 9 6 10 4 3
2
限制
1s, 10240KiB for each test case.
#include <iostream>
#include <string>
#include <cstring>
#include <queue>
#define MNum 100003 //最大顶点数;using namespace std;bool vist[MNum]; //顶点标记数组;
int ff = 0;typedef struct ANode
{ //定义边结点;int adv; //该边所指向的顶点的位置;struct ANode *next; //指向下一条边的指针;
} ArcNode;typedef struct VNode
{ //定义表头结点;ANode *firstNode; //指向第一条依附于该表头的指针;int element; //存放定点信息;
} AdVList;struct ALGraph
{ //邻接表;AdVList VLise[MNum]; //创建有MNum个结点的图;int Vnum, Anum; //图的定点数和边数;
};class Graph
{
public:// 构造函数Graph(int n = 100){G.Vnum = n; // 确定图的定点个数for (int i = 0; i < n; i++) // 建立一个指针数组,用于安排定点的存放{G.VLise[i].element = i + 1;G.VLise[i].firstNode = NULL;}}void bfsCounter(int n); // bfs长度void insert(int v1, int v2); // 插入void erase(int v1, int v2); // 删除void bfs(int n); // bfs最小序列void dfs(int n); // dfs最小序列void fdfs(int n); // 计算连通分量函数的辅助函数void components(int n); // 计算连同分量void dfsCounter(int n); // dfs长度void path2(int x, int y); // 最短路径求解void everyComponents(int n); // 每个连同分量的最小元素protected:ALGraph G;
};// 添加边
void Graph::insert(int v1, int v2)
{int j, k;j = v1 - 1; // 找到节点的位置k = v2 - 1;ANode *p1 = new ANode; // 定义两个边表节点ANode *p2 = new ANode;p1->adv = k;ANode *p = G.VLise[j].firstNode;ANode *pp = NULL;if (p == NULL || p->adv > k){p1->next = G.VLise[j].firstNode;G.VLise[j].firstNode = p1;}else{while (p && p->adv < k){pp = p;p = p->next;}if (!p){pp->next = p1;p1->next = NULL;}else{p1->next = pp->next;pp->next = p1;}}ANode *q1 = new ANode;ANode *q2 = new ANode;q1->adv = j;ANode *q = G.VLise[k].firstNode;ANode *qq = NULL;if (q == NULL || q->adv > j){ // 插入节点并对节点的顺序进行从小到大排序q1->next = G.VLise[k].firstNode; // (头插法)G.VLise[k].firstNode = q1;}else{while (q && q->adv < j){ // 查找比插入的节点大的值qq = q;q = q->next;}if (!q){ // 查到最后一个节点(末尾插入)qq->next = q1;q1->next = NULL;}else{ // 没有查到最后的节点(中间插入)q1->next = qq->next;qq->next = q1;}}G.Anum++; // 边数加一
}// 删除边
void Graph::erase(int v1, int v2)
{v1 = v1 - 1; // 找到节点的位置v2 = v2 - 1;ANode *current = G.VLise[v2].firstNode; // 找到其中一个定点的头结点ANode *trail = NULL;while (current != NULL && current->adv != v1){ // 寻找需要删除的边的另一个节点trail = current;current = current->next;}if (current == NULL){ // 需要删除的边不存在cout << "none" << endl;return;}if (trail != NULL) // 判断删除的是否是头结点(不是头结点)trail->next = current->next;else // 头结点G.VLise[v2].firstNode = current->next;delete current; // 删除节点// 同理实现另一个节点方面的删除ANode *current2 = G.VLise[v1].firstNode;ANode *trail2 = NULL;while (current2 != NULL && current2->adv != v2){trail2 = current2;current2 = current2->next;}if (current2 == NULL){cout << "none" << endl;return;}if (trail2 != NULL)trail2->next = current2->next;elseG.VLise[v1].firstNode = current2->next;delete current2;G.Anum--; // 边数减一
}// dfs
void Graph::dfs(int n)
{cout << G.VLise[n].element; // 输出起点的值vist[n] = false; // 对输出的值进行标记ANode *p = G.VLise[n].firstNode; // 定义一个指针在该链表遍历while (p) // 只要p不为空就继续执行{if (vist[p->adv]) // 判断是否已经输出{cout << " ";dfs(p->adv); // 递归(深度遍历)}p = p->next; // 节点后移}
}void Graph::fdfs(int n)
{vist[n] = false;ANode *p = G.VLise[n].firstNode;while (p){if (vist[p->adv]){fdfs(p->adv);}p = p->next;}
}void Graph::dfsCounter(int n)
{vist[n] = false;ANode *p = G.VLise[n].firstNode;ff++; // 进行长度的记录while (p){if (vist[p->adv]){dfsCounter(p->adv);}p = p->next;}
}// bfs
void Graph::bfs(int n)
{queue<int> q; // 定义一个队列q.push(n); // 将起点压入队列中while (!q.empty()){cout << G.VLise[q.front()].element << " "; // 输出队首vist[q.front()] = false; // 标记队首已输出ANode *p = G.VLise[q.front()].firstNode;while (p) // 将p指针指向的节点的链表全部压入队列中{if (vist[p->adv]){vist[p->adv] = false;q.push(p->adv);}p = p->next;}q.pop(); // 删除队首}cout << endl;
}// 连通分量
void Graph::components(int n)
{memset(vist, true, sizeof(vist));int i, flag = 0;for (i = 0; i < n; i++){if (vist[i] == true) // 使用dfs的方法,进行链表上的节点标记,当有节点在某一条节点上标记时,连通分量加一{fdfs(i);flag++;}}cout << flag << endl;memset(vist, true, sizeof(vist)); // 最后将所有节点的标记去除
}void Graph::everyComponents(int n) // 同计算连通分量的方法一样(因为每一次插入都进行了排序,直接输出链表的第一个元素即可
{memset(vist, true, sizeof(vist));int i;for (i = 0; i < n; i++){if (vist[i] == true){cout << i + 1 << " ";fdfs(i);}}memset(vist, true, sizeof(vist));cout << endl;
}void Graph::path2(int x, int y)
{queue<int> q; // 队列int num = G.Vnum + 1;q.push(x); // 压入起点vist[q.front()] = false; // 标记int path[num]; // 定义一个数组(用于记录路径长度)for (int i = 0; i < num; i++)path[i] = 0; // 数组初始化while (!q.empty()) // 在链表中查找时(查询直到链表末尾){int w = q.front(); // 起点q.pop();ANode *p = G.VLise[w].firstNode;while (p != NULL){if (vist[p->adv]) // 如果没有被标记// 一个节点的所有下一个节点路径长度都相同,所以可以实现最短路径的实现{if (p->adv == y) // 判读是否为终点{cout << path[w] + 1 << endl; // 输出长度return;}path[p->adv] = path[w] + 1; // 下一个节点都在这个节点的基础上进行加一操作q.push(p->adv); // 压入下一个节点vist[p->adv] = false; // 标记}p = p->next;}}cout << "-1" << endl;
}void Graph::bfsCounter(int n)
{queue<int> q; // 定义一个队列q.push(n); // 将起点压入队列中ff++; // 起点进行加一操作while (!q.empty()){vist[q.front()] = false; // 标记队首已输出ANode *p = G.VLise[q.front()].firstNode;while (p) // 将p指针指向的节点的链表全部压入队列中{if (vist[p->adv]){vist[p->adv] = false;q.push(p->adv);ff++; // 压入一个就进行加一操作,进行计数}p = p->next;}q.pop(); // 删除队首}
}
int main()
{int n, s, t;int m;cin >> n >> m >> s >> t;Graph A(n);for (int i = 0; i < m; i++) // 结下来m行输入{int op;cin >> op;if (op == 0){int v1, v2;cin >> v1 >> v2;A.insert(v1, v2);}else if (op == 1){int v1, v2;cin >> v1 >> v2;A.erase(v1, v2);}}A.components(n); // 第一行输出图中有多少个连通分量A.everyComponents(n); // 第二行输出所有连通子图中最小点的编号(升序),编号间用空格分隔A.dfsCounter(s - 1); // 第三行输出从s点开始的dfs序列长度(ff记录长度)cout << ff << endl;ff = 0;memset(vist, true, sizeof(vist));A.dfs(s - 1); // 第四行输出dfs最小序列cout << endl;memset(vist, true, sizeof(vist));A.bfsCounter(t - 1);cout << ff << endl; //第五行输出从t点开始的bfs序列的长度ff = 0;memset(vist, true, sizeof(vist));A.bfs(t - 1); // 第六行输出bfs序列memset(vist, true, sizeof(vist));A.path2(s - 1, t - 1); // 第七行输出从s点到t点的最短路径,若是不存在路径则输出-1return 0;
}
Vj数据结构实验十二相关推荐
- 【黑金原创教程】【FPGA那些事儿-驱动篇I 】实验十二:串口模块① — 发送
实验十二:串口模块① - 发送 串口固然是典型的实验,想必许多同学已经作烂,不过笔者还要循例介绍一下.我们知道串口有发送与接收之分,实验十二的实验目的就是实现串口发送,然而不同的是 ... 笔者会用另 ...
- 虚拟机dhcp服务器怎么检验,实验十二虚拟机上DHCP服务器的配置和验证.doc
实验十二 虚拟机上DHCP服务器的配置与验证 一.实验目的 了解DHCP的基本概念和服务器的新特性 掌握DHCP服务器的安装与配置 掌握DHCP的运行方式 掌握DHCP客户机的设置 掌握ipconfi ...
- 实验十二 HTTP 协议分析实验
实验十二 HTTP 协议分析实验 1.HTTP 协议简介 HTTP是超文本传输协议 (Hyper Text Transfer Protocol)的缩写,用于WWW 服务. (1)HTTP的工作原理 H ...
- 实验十二、十三 配置PPP协议、配置Frame-relay协议
实验十二 配置PPP协议 要求: 配置PPP协议,实现广域网连接.然后,分别采用PAP和CHAP进行验证,最后启用OSPF协议,实现局域网之间相互通信. 基础配置 为路由器R1.R2设置相应的 ...
- 计算机组成原理Rsel什么意思,el-jy-ⅱ 计算机组成原理第二套 实验十二
el-jy-ⅱ 计算机组成原理第二套 实验十二 (9页) 本资源提供全文预览,点击全文预览即可全文预览,如果喜欢文档就下载吧,查找使用更方便哦! 19.90 积分 梁旷啦倔洲湿悔胚啼铆止羊香蔫夏髓解师 ...
- 同步检波 matlab,实验十二 包络检波及同步检波实验
实验十二 包络检波及同步检波实验 一.实验目的 1.进一步了解调幅波的原理,掌握调幅波的解调方法. 2.掌握二极管峰值包络检波的原理. 3.掌握包络检波器的主要质量指标,检波效率及各种波形失真的现象, ...
- 操作系统真象还原实验记录之实验十二:实现ASSERT
操作系统真象还原实验记录之实验十二:实现ASSERT,通过makefile完成编译 对应书P367 第8.2节 1.相关基础知识 见书 2.实验代码 完成了开关中断函数.实现assert断言函数用于调 ...
- 实验十一 .实验十二
一.程序代码 package jisuanqi2; import java.awt.*; import javax.swing.*; import java.awt.event.*; public c ...
- 离散时间系统的时域分析 matlab,实验十二离散时间系统时域分析的MATLAB实现.doc...
您所在位置:网站首页 > 海量文档  > 计算机 > matlab 实验十二离散时间系统时域分析的MATLAB实现.d ...
最新文章
- [Android1.5]Android2.0版本以下Activity切换动画效果
- 在fstab下添加网络启动设备
- links下c语言中for的作用是,C语言开发注意事项
- Hello World, S/4HANA for Customer Management 1.0 1
- ORA-27101 Shared memory realm does not exist 之解決 (转)
- 逻辑代码题:五个学生参加计算机比赛
- 深度学习2.0-35.ResNet-18实战
- method swizzling你应该注意的点
- Allegro给一个网络赋默认值,取消默认值
- oracle里面的double,oracle建表语句double
- junit 单元测试插入操作事务回滚
- 三星30pin引脚_USB3.0针脚定义、引脚定义(精校版本)
- Riot Game前高管:游戏玩家将成为Web3真正粉丝的15大原因
- 25岁,上帝找你谈一次灵魂。——送给女孩,也送给男孩
- Windows 7驱动自动安装设置及手动更新方法
- ReactNative 公共脱敏处理js 包括银行卡 身份证号 手机号企业名称 营业执照 邮箱号码 等等
- 桂林理工研究生院计算机软件工程,2019桂林理工大学硕士研究生复试细则之软件工程...
- java调用百望税控NISEC_SKSC.dll发送xml报文
- 纯数学教程 Page 324 正项级数绝对收敛的一种判别法
- Leetcode刷题笔记12:【20】有效的括号【155】最小栈【255】用队列实现栈(STL:stackC++ 单引号和双引号)