【2020年天梯赛校选赛】7-14 战争地图!(邻接矩阵版本)

【2020年天梯赛校选赛】7-14 战争地图!(邻接矩阵版本)

由于叛徒朱子明的出卖,导致独立团在赵家峪的团部驻军在团长李云龙大婚之日几乎全军覆没。
突出重围之后,李云龙决定集合所有驻扎在外的部队,使用重型武器意大利炮攻打平安县城!
消息从团部穿出之后到达各部驻地后,驻地长官会派出自己的通讯人员通知其他部队。但是一旦该驻地被攻陷,那么该驻地就无法收到命令,同理与该驻地有道路连通的驻地也无法收到命令!
现在,李云龙想知道假设一个驻地被攻陷,所有的驻地会被分为几个连通块!
为了简化问题,不要求计算每个连通块的具体信息,只要求输出连通块的数量即可!

输入格式:
第一行包含两个正整数N(N<=1000)和M(<=2000),表示整个战区一共有N个驻地,这N个驻地由M条无向小道相连!(驻地由1到N编号)
接下来M行,每行包含两个驻地编号,表示这两个驻地之间有一条小道相连!
接下来一行包含一个正整数q,表示有q个询问!
接下来q行,每行包含一个驻地编号!

输出格式:
对于每个询问,请你输出在删掉它和所有与它相连的小道之后,这个战区的驻地形成的连通块数量!
值得注意的一点是,每个询问相互独立!

输入样例:
在这里给出一组输入。例如:
8 8
1 2
1 4
2 3
4 3
3 5
5 7
5 6
5 8
3
3
5
7

输出样例:
在这里给出相应的输出。例如:
2
4
1

代码:

#include <iostream>					//7-9 战争地图!(邻接矩阵版本)
#include <algorithm>
#include <queue>
#include <cstring>
using namespace std;
const int MaxV = 1002;	//最大顶点数

int N, M;			//输入顶点数与边数
bool Vis[MaxV];		//标记是否访问

/*邻接表需要的结构定义*/
typedef struct ENode{
	int v1, v2;
} * Edge;
struct AdjVNode{
	int AdjV;
	AdjVNode *Next;
};
typedef struct VNode{
	AdjVNode *FirstEdge;
} AdjList[MaxV];
typedef struct GNode{
	int Nv, Ne;
	AdjList L;
} * LGraph;

void InsertEdge(LGraph G, Edge E)		//插入无向边
{
	AdjVNode *A;
	A = new AdjVNode;
	A->AdjV = E->v1;
	A->Next = G->L[E->v2].FirstEdge;
	G->L[E->v2].FirstEdge = A;

	A = new AdjVNode;
	A->AdjV = E->v2;
	A->Next = G->L[E->v1].FirstEdge;
	G->L[E->v1].FirstEdge = A;
}

void DestroyGraph(LGraph G)				//释放内存
{
	AdjVNode *A;
	for (int i = 1; i <= G->Nv; i++)
		while (G->L[i].FirstEdge)
		{
			A = G->L[i].FirstEdge;
			G->L[i].FirstEdge = A->Next;
			delete A;
		}
	delete G;
}

int BFS(int k, LGraph G)		//用BFS统计连通分量个数
{
	int ans = 0;
	Vis[k] = true;
	queue<int> q;
	AdjVNode *A;

	for (int i = 1; i <= G->Nv; i++)
	{
		if(Vis[i])
			continue;
		q.push(i);
		while (!q.empty())		//应用BFS搜索
		{
			int k = q.front();
			q.pop();
			A = G->L[k].FirstEdge;
			while (A)
			{
				if(!Vis[A->AdjV])
					Vis[A->AdjV] = true, q.push(A->AdjV);
				A = A->Next;
			}
		}
		ans++;
	}
	return ans;
}

int main()
{
	int x, y;
	cin >> N >> M;
	LGraph G = new GNode();
	G->Nv = N, G->Ne = M;

	Edge E = new ENode;
	for (int i = 0; i < M; i++)
	{
		cin >> E->v1 >> E->v2;
		InsertEdge(G, E);
	}
	delete E;		//记得释放内存

	/*输入并测试*/
	int T, k;
	cin >> T;
	while (T--)
	{
		cin >> k;
		memset(Vis, false, sizeof(Vis));
		cout << BFS(k, G) << endl;
	}
	DestroyGraph(G);	//释放图的内存

	system("pause");
	return 0;
}

内容简介   本书从Windows内核编程出发,全面系统地介绍了串口、键盘、磁盘、文件系统、网络等相关的Windows内核模块的编程技术,以及基于这些技术实现的密码保护、防毒引擎、文件加密、网络嗅探、网络防火墙等信息安全软件的核心组件的具体编程。主要知识重点包括:Windows串口与键盘过滤驱动、Windows虚拟存储设备与存储设备过滤驱动、Windows文件系统过滤驱动、文件系统透明加密/解密驱动、Windows各类网络驱动(包括TDI过滤驱动及三类NDIS驱动),以及最新的WDF驱动开发模型。有助于读者熟悉Windows内核驱动的体系结构,并精通信息安全类的内核编程技术。本书的大部分代码具有广泛的兼容性,适合从Windows 2000 一直到目前最新的Windows 7 Beta 版。   本书适合大专院校计算机系的学生、普通Windows程序员、Windows内核程序员、信息安全行业的程序员,以及希望了解Windows系统底层知识的计算机编程爱好者使用。阅读本书,需要读者有C语言、数据结构、操作系统和计算机网络的基础知识。 目录: 封面 -25 扉页 -24 内容简介 -23 序 -22 关于本书作者和贡献者 -20 前言 -18 阅读注意 -16 目录 -12 正文 1 第1章 内核上机指导 1 1.1 下载和使用WDK 2 1.1.1 下载安装WDK 2 1.1.2 编写第一个C文件 3 1.1.3 编译一个工程 5 1.2 安装与运行 6 1.2.1 下载一个安装工具 6 1.2.2 运行与查看输出信息 7 1.2.3 在虚拟机中运行 9 1.3 调试内核模块 9 1.3.1 下载和安装WinDbg 9 1.3.2 设置Windows XP 调试执行 10 1.3.3 设置Vista调试执行 11 1.3.4 设置VMWare的管道虚拟串口 11 1.3.5 设置Windows内核符号表 13 1.3.6 实战调试first 14 练习题 16 第2章 内核编程环境及其特殊性 17 2.1 内核编程的环境 18 2.1.1 隔离的应用程序 18 2.1.2 共享的内核空间 19 2.1.3 无处不在的内核模块 20 2.2 数据类型 21 2.2.1 基本数据类型 21 2.2.2 返回状态 22 2.2.3 字符串 23 2.3 重要的数据结构 23 2.3.1 驱动对象 23 2.3.2 设备对象 25 2.3.3 请求 26 2.4 函数调用 28 2.4.1 查阅帮助 28 2.4.2 帮助中有的几类函数 30 2.4.3 帮助中没有的函数 32 2.5 Windows的驱动开发模型 32 2.6 WDK编程中的特殊点 33 2.6.1 内核编程的主要调用源 33 2.6.2 函数的多线程安全性 34 2.6.3 代码的中断级 36 2.6.4 WDK中出现的特殊代码 37 练习题 38 第3章 串口的过滤 40 3.1 过滤的概念 41 3.1.1 设备绑定的内核API之一 41 3.1.2 设备绑定的内核API之二 43 3.1.3 生成过滤设备并绑定 43 3.1.4 从名字获得设备对象 45 3.1.5 绑定所有串口 46 3.2 获得实际数据 47 3.2.1 请求的区分 47 3.2.2 请求的结局 48 3.2.3 写请求的数据 49 3.3 完整的代码 50 3.3.1 完整的分发函数 50 3.3.2 如何动态卸载 52 3.3.3 完整的代码 53 本章的示例代码 53 练习题 54 第4章 键盘的过滤 56 4.1 技术原理 57 4.1.1 预备知识 57 4.1.2 Windows中从击键到内核 58 4.1.3 键盘硬件原理 60 4.2 键盘过滤的框架 61 4.2.1 找到所有的键盘设备 61 4.2.2 应用设备扩展 64 4.2.3 键盘过滤模块的DriverEntry 65 4.2.4 键盘过滤模块的动态加载 66 4.3 键盘过滤的请求处理 68 4.3.1 通常的处理 68 4.3.2 PNP的处理 69 4.3.3 读的处理 70 4.3.4 读完成的处理 71 4.4 从请求中打印出按键信息 72 4.4.1 从缓冲区中获得KEYBOARD_INPUT_DATA 72 4.4.2 从KEYBOARD_INPUT_DATA中得到键 73 4.4.3 从MakeCode到实际字符 74 4.5 Hook分发函数 75 4.5.1 获得类驱动对象 76 4.5.2 修改类驱动的分发函数指针 77 4.5.3 类驱动之下的端口驱动 78 4.5.4 端口驱动和驱动之间的协作机制 79 4.5.5 找到关键的回调函数的条件 80 4.5.6 定义常数和数据结构
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值