描述

创建无向图类,存储结构使用邻接链表,提供操作:插入一条边,删除一条边,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数据结构实验十二相关推荐

  1. 【黑金原创教程】【FPGA那些事儿-驱动篇I 】实验十二:串口模块① — 发送

    实验十二:串口模块① - 发送 串口固然是典型的实验,想必许多同学已经作烂,不过笔者还要循例介绍一下.我们知道串口有发送与接收之分,实验十二的实验目的就是实现串口发送,然而不同的是 ... 笔者会用另 ...

  2. 虚拟机dhcp服务器怎么检验,实验十二虚拟机上DHCP服务器的配置和验证.doc

    实验十二 虚拟机上DHCP服务器的配置与验证 一.实验目的 了解DHCP的基本概念和服务器的新特性 掌握DHCP服务器的安装与配置 掌握DHCP的运行方式 掌握DHCP客户机的设置 掌握ipconfi ...

  3. 实验十二 HTTP 协议分析实验

    实验十二 HTTP 协议分析实验 1.HTTP 协议简介 HTTP是超文本传输协议 (Hyper Text Transfer Protocol)的缩写,用于WWW 服务. (1)HTTP的工作原理 H ...

  4. 实验十二、十三 配置PPP协议、配置Frame-relay协议

    实验十二     配置PPP协议 要求: 配置PPP协议,实现广域网连接.然后,分别采用PAP和CHAP进行验证,最后启用OSPF协议,实现局域网之间相互通信. 基础配置 为路由器R1.R2设置相应的 ...

  5. 计算机组成原理Rsel什么意思,el-jy-ⅱ 计算机组成原理第二套 实验十二

    el-jy-ⅱ 计算机组成原理第二套 实验十二 (9页) 本资源提供全文预览,点击全文预览即可全文预览,如果喜欢文档就下载吧,查找使用更方便哦! 19.90 积分 梁旷啦倔洲湿悔胚啼铆止羊香蔫夏髓解师 ...

  6. 同步检波 matlab,实验十二 包络检波及同步检波实验

    实验十二 包络检波及同步检波实验 一.实验目的 1.进一步了解调幅波的原理,掌握调幅波的解调方法. 2.掌握二极管峰值包络检波的原理. 3.掌握包络检波器的主要质量指标,检波效率及各种波形失真的现象, ...

  7. 操作系统真象还原实验记录之实验十二:实现ASSERT

    操作系统真象还原实验记录之实验十二:实现ASSERT,通过makefile完成编译 对应书P367 第8.2节 1.相关基础知识 见书 2.实验代码 完成了开关中断函数.实现assert断言函数用于调 ...

  8. 实验十一 .实验十二

    一.程序代码 package jisuanqi2; import java.awt.*; import javax.swing.*; import java.awt.event.*; public c ...

  9. 离散时间系统的时域分析 matlab,实验十二离散时间系统时域分析的MATLAB实现.doc...

    您所在位置:网站首页 > 海量文档 &nbsp>&nbsp计算机&nbsp>&nbspmatlab 实验十二离散时间系统时域分析的MATLAB实现.d ...

最新文章

  1. [Android1.5]Android2.0版本以下Activity切换动画效果
  2. 在fstab下添加网络启动设备
  3. links下c语言中for的作用是,C语言开发注意事项
  4. Hello World, S/4HANA for Customer Management 1.0 1
  5. ORA-27101 Shared memory realm does not exist 之解決 (转)
  6. 逻辑代码题:五个学生参加计算机比赛
  7. 深度学习2.0-35.ResNet-18实战
  8. method swizzling你应该注意的点
  9. Allegro给一个网络赋默认值,取消默认值
  10. oracle里面的double,oracle建表语句double
  11. junit 单元测试插入操作事务回滚
  12. 三星30pin引脚_USB3.0针脚定义、引脚定义(精校版本)
  13. Riot Game前高管:游戏玩家将成为Web3真正粉丝的15大原因
  14. 25岁,上帝找你谈一次灵魂。——送给女孩,也送给男孩
  15. Windows 7驱动自动安装设置及手动更新方法
  16. ReactNative 公共脱敏处理js 包括银行卡 身份证号 手机号企业名称 营业执照 邮箱号码 等等
  17. 桂林理工研究生院计算机软件工程,2019桂林理工大学硕士研究生复试细则之软件工程...
  18. java调用百望税控NISEC_SKSC.dll发送xml报文
  19. 纯数学教程 Page 324 正项级数绝对收敛的一种判别法
  20. Leetcode刷题笔记12:【20】有效的括号【155】最小栈【255】用队列实现栈(STL:stackC++ 单引号和双引号)

热门文章

  1. Scrapy使用报错socket.timeout: timed out
  2. 跨境电商亚马逊广告的六大痛点,九大思维误区
  3. 数控等离子切割机,等离子切割机
  4. 树莓派 usb与电脑windows系统进行485通讯
  5. java.lang.NullPointerException:null
  6. 网页的大哥——HTML
  7. python b站 排行_Python 爬取B站 视频热度排行数据
  8. 特征工程-获取更好的训练数据
  9. Normal.dotm正由另一程序占用或者用户占用 解决方法
  10. 2018 年度代码报告