洛谷 P5318 【深基18.例3】查找文献

这篇具有很好参考价值的文章主要介绍了洛谷 P5318 【深基18.例3】查找文献。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

【题目链接】

洛谷 P5318 【深基18.例3】查找文献

【题目考点】

1. 图论:深度优先遍历
2. 图论:广度优先遍历

【解题思路】

首先将题目描述抽象为拓扑图,这是一个有向图,每篇文章是顶点,边<x,y>表示文章x有参考文献y。
“目前小K已经打开了编号为1的一篇文章”,意为只从1号顶点出发开始进行搜索。要做的是从1号顶点一趟搜索,并不需要把给出的所有文章都遍历到。
邻接矩阵的空间复杂度是 O ( V 2 ) O(V^2) O(V2),邻接表的空间复杂度是 O ( V + E ) O(V+E) O(V+E),该题中顶点数V达到 1 0 5 10^5 105,边数E达到 1 0 6 10^6 106。如果使用邻接矩阵,声明变量的数量会达到 1 0 10 10^{10} 1010,是不可接受的(最大可以到 1 0 7 10^7 107)。
因此本题只能使用邻接表求解。

“如果有很多篇文章可以参阅,请先看编号较小的那篇”:
如果使用邻接表保存,那么vector<int>类型的edge[u]中保存的u的邻接点必须是从小到大排列的。
实现方法有以下几种,复杂度都是 O ( n ) O(n) O(n)文章来源地址https://www.toymoban.com/news/detail-673822.html

//vec插入数值v,保持vec中的元素是升序的
//方法1:插入排序
void seqIns1(vector<int> &vec, int v)
{
	vec.push_back(v);
	for(int i = vec.size()-1; i > 0; --i)
		if(vec[i] < vec[i-1])
			swap(vec[i], vec[i-1]); 
}
//方法2:顺序查找待插入的位置并插入
void seqIns2(vector<int> &vec, int v)
{
	vector<int>::iterator it;
	for(it = vec.begin(); it != vec.end(); ++it)
		if(*it >= v)
			break;
	vec.insert(it, v);//迭代器it指向第一个大于等于v的最小值,在it指向的元素前面插入v
}
//方法3:二分查找待插入位置并插入
void seqIns3(vector<int> &vec, int v)
{
	vec.insert(lower_bound(vec.begin(), vec.end(), v), v); 
}

【题解代码】

解法1:使用邻接表
  • 写法1:插入排序构造有序vector
#include<bits/stdc++.h>
using namespace std;
#define N 100005
vector<int> edge[N];//edge[i]:保存i的所有邻接点 
bool vis[N];//vis[i]:顶点i是否已访问 
int n, m;//n:顶点数 m:边数 
void dfs(int u)
{
	for(int v : edge[u])
	{
		if(vis[v] == false)
		{
			vis[v] = true;
			cout << v << ' ';
			dfs(v);
		}
	}
}
void bfs(int sv)
{
	queue<int> que;
	vis[sv] = true;
	cout << sv << ' ';
	que.push(sv);
	while(que.empty() == false)
	{
		int u = que.front();
		que.pop();
		for(int v : edge[u])
		{
			if(vis[v] == false)
			{
				vis[v] = true;
				cout << v << ' ';
				que.push(v);
			}
		}
	}
}
void seqIns(int f, int t)//顶点f添加邻接点t,保持edge[f]升序 
{
	edge[f].push_back(t);
	for(int i = edge[f].size()-1; i > 0; --i)
		if(edge[f][i] < edge[f][i-1])
			swap(edge[f][i], edge[f][i-1]); 
}
int main(){
    int f, t;
    cin >> n >> m;
    for(int i = 1; i <= m; i++){
    	cin >> f >> t;
    	seqIns(f, t);
	}
	vis[1] = true;
	cout << 1 << ' ';
	dfs(1);
	cout<<endl;
	memset(vis,false,sizeof(vis));
	bfs(1);
    return 0;
}
  • 写法2:二分查找加插入构造有序vector
#include<bits/stdc++.h>
using namespace std;
#define N 100005
vector<int> edge[N];//edge[i]:保存i的所有邻接点 
bool vis[N];//vis[i]:顶点i是否已访问 
int n, m;//n:顶点数 m:边数 
void dfs(int u)
{
	for(int v : edge[u])
	{
		if(vis[v] == false)
		{
			vis[v] = true;
			cout << v << ' ';
			dfs(v);
		}
	}
}
void bfs(int sv)
{
	queue<int> que;
	vis[sv] = true;
	cout << sv << ' ';
	que.push(sv);
	while(que.empty() == false)
	{
		int u = que.front();
		que.pop();
		for(int v : edge[u])
		{
			if(vis[v] == false)
			{
				vis[v] = true;
				cout << v << ' ';
				que.push(v);
			}
		}
	}
}
int main(){
    int f, t;
    cin >> n >> m;
    for(int i = 1; i <= m; i++){
    	cin >> f >> t;
    	edge[f].insert(lower_bound(edge[f].begin(), edge[f].end(), t), t);
	}
	vis[1] = true;
	cout << 1 << ' ';
	dfs(1);
	cout<<endl;
	memset(vis,false,sizeof(vis));
	bfs(1);
    return 0;
}

到了这里,关于洛谷 P5318 【深基18.例3】查找文献的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 算法题目题单+题解——图论

    本文为自己做的一部分图论题目,作为题单列出,持续更新。 题单由题目链接和题解两部分组成,题解部分提供简洁题意,代码仓库:Kaiser-Yang/OJProblems。 对于同一个一级标题下的题目,题目难度尽可能做到递增。 题目链接:Luogu P3547 [POI2013] CEN-Price List 题解: 题目链接:

    2024年02月19日
    浏览(25)
  • 每天一道leetcode:1192. 查找集群内的关键连接(图论&困难&tarjan算法)

    力扣数据中心有 n 台服务器,分别按从 0 到 n-1 的方式进行了编号。它们之间以 服务器到服务器 的形式相互连接组成了一个内部集群,连接是无向的。用 connections 表示集群网络, connections[i] = [a, b] 表示服务器 a 和 b 之间形成连接。任何服务器都可以直接或者间接地通过网络

    2024年02月12日
    浏览(33)
  • 【算法专题突破】二分查找 - x 的平方根(18)

    目录 1. 题目解析 2. 算法原理 3. 代码编写 写在最后: 题目链接:69. x 的平方根 - 力扣(LeetCode) 这道题就是求算数平方根, 要注意的点是他只需要保留整数部分,小数部分会舍去 我们确定好一个区间 1 ~ x,数字 x 的算数平方根一定在这里面, 最简单的思路就是用暴力解法

    2024年02月07日
    浏览(28)
  • 洛谷P1249题解

    一个正整数一般可以分为几个互不相同的自然数的和,如 3 = 1 + 2 3=1+2 3 = 1 + 2 , 4 = 1 + 3 4=1+3 4 = 1 + 3 , 5 = 1 + 4 = 2 + 3 5=1+4=2+3 5 = 1 + 4 = 2 + 3 , 6 = 1 + 5 = 2 + 4 6=1+5=2+4 6 = 1 + 5 = 2 + 4 。 现在你的任务是将指定的正整数 n n n 分解成若干个互不相同的自然数的和,且使这些自

    2024年02月05日
    浏览(42)
  • 洛谷 P8742题解

    简单版(P2347)传送门 原题传送门 有一道 类似 的题目(P2347),先扯一扯~ 动态规划入门题(01背包 可行性问题 )~ 我们 设 (dp_j) 为能否用砝码称出 (j) 重量 ,1 为 可以 ,0 为 不可以 。 为了转移, (dp_{_{0}} gets 1) , 什么都不放时,重量为 0 ,因此可以称出。 那么 枚举

    2024年02月06日
    浏览(44)
  • 洛谷 CF1743APassword 题解

    https://www.luogu.com.cn/problem/CF1743A 已知一个长度为四的,只包含字符 0 , 1 , 2 , … , 9 0,1,2,dots ,9 0 , 1 , 2 , … , 9 的字符串中不会出现哪些字符,求可能的字符串的数量。 Monocarp has forgotten the password to his mobile phone. The password consists of $ 4 $ digits from $ 0 $ to $ 9 $ (note that it can start wit

    2023年04月20日
    浏览(34)
  • 洛谷AT4888 题解-伦伦数

    A positive integer XX is said to be a lunlun number if and only if the following condition is satisfied: In the base ten representation of XX (without leading zeros), for every pair of two adjacent digits, the absolute difference of those digits is at most 11 . For example, 12341234 , 11 , and 334334 are lunlun numbers, while none of 3141531415 

    2024年02月06日
    浏览(34)
  • 洛谷题单 -- 图论的简单入门

    图的存储 - 洛谷 这一题要考察图的存储方式 , 一般可以使用邻接矩阵 或 邻接表来存储 图的结点 和1 边的信息 ,详情请看代码 :  【深基18.例3】查找文献 - 洛谷 这题考察有向图的 dfs 和 bfs ,详情请看代码,如果用邻接矩阵的话一定会mle,只能够使用邻接表,我这里采用的是用

    2024年04月13日
    浏览(33)
  • 洛谷 P1336 最佳课题选择 题解

    题目链接 状态:考虑 (f_{i,j}) 表示前 (i) 种论文里面,一共写了 (j) 篇,的最少花费时间。 转移策略:我们一次考虑每一种论文写多少篇。假设写 (k) 篇, (k in [0,j] cap mathbb{Z}) ,有转移方程: [f_{i,j} = min(f_{i-1,j-k} + text{cost}(i,k)), k in [0,j] cap mathbb{Z}] 其中 [text{

    2024年02月14日
    浏览(29)
  • 洛谷 P1122 最大子树和 题解

    一道入门的树形DP。 首先我们对于数据进行有序化处理,这便于我们利用数据结构特点(可排序性)来发觉数据性质(有序、单调、子问题等等性质),以便于后续的转化、推理和处理。 有序化可以“转化和创造”性质 首先将视角从无根树切换为有根树,这样我们就可以得

    2024年02月17日
    浏览(25)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包