# 查找文献
## 题目描述
小K 喜欢翻看洛谷博客获取知识。每篇文章可能会有若干个(也有可能没有)参考文献的链接指向别的博客文章。小K 求知欲旺盛,如果他看了某篇文章,那么他一定会去看这篇文章的参考文献(如果他之前已经看过这篇参考文献的话就不用再看它了)。
假设洛谷博客里面一共有 n(n<=10^5) 篇文章(编号为 1 到 n)以及 m(m<=10^6) 条参考文献引用关系。目前小 K 已经打开了编号为 1 的一篇文章,请帮助小 K 设计一种方法,使小 K 可以不重复、不遗漏的看完所有他能看到的文章。
这边是已经整理好的参考文献关系图,其中,文献 X → Y 表示文章 X 有参考文献 Y。不保证编号为 1 的文章没有被其他文章引用。
![](https://cdn.luogu.com.cn/upload/image_hosting/f4n4tlhi.png)
请对这个图分别进行 DFS 和 BFS,并输出遍历结果。如果有很多篇文章可以参阅,请先看编号较小的那篇(因此你可能需要先排序)。
## 输入格式
共 m+1 行,第 1 行为 2 个数,n和 m,分别表示一共有 n(n<=10^5) 篇文章(编号为 1 到 n)以及m(m<=10^6) 条参考文献引用关系。
接下来 m 行,每行有两个整数 X,Y 表示文章 X 有参考文献 Y。
## 输出格式
共 2 行。
第一行为 DFS 遍历结果,第二行为 BFS 遍历结果。
## 样例 #1
### 样例输入 #1
```
8 9
1 2
1 3
1 4
2 5
2 6
3 7
4 7
4 8
7 8
```
### 样例输出 #1
```
1 2 5 6 3 7 8 4
1 2 3 4 5 6 7 8
```
解题思路:先用邻接表存图,然后根据终点大小从小到大排序,
再用dfs和bfs,并用两个数组分别存遍历的数
完整代码如下:
```cpp
#include <bits/stdc++.h>
using namespace std;
const int maxn=1e6+5;
bool dvis[maxn],bvis[maxn];
vector<int> e[maxn];
int cnt,a[maxn],ans,b[maxn];
void dfs(int u);
void bfs(int u);
int main()
{
int n,m;
cin>>n>>m;
int u,v;
for(int i=1 ;i<=m; i++){
cin>>u>>v;
e[u].push_back(v);
}//邻接表存图
for(int i=1; i<=n; i++) sort(e[i].begin(),e[i].end());//根据终点从小到大排序
dvis[1]=1;
dfs(1);
for(int i=0; i<=cnt; i++) cout<<a[i]<<" ";
cout<<endl;
bfs(1);
for(int i=0; i<=ans; i++) cout<<b[i]<<" ";
return 0;
}
void dfs(int u)
{
a[cnt]=u;
for(int i=0; i<e[u].size(); i++){
if(!dvis[e[u][i]]){
cnt++;
dvis[e[u][i]]=1;
dfs(e[u][i]);
}
}
}
void bfs(int u)
{
queue <int> q;
q.push(u);
b[ans]=u;
bvis[u]=1;
while(!q.empty()){
int t=q.front();
q.pop();
for(int i=0; i<e[t].size(); i++){
if(!bvis[e[t][i]]){
b[++ans]=e[t][i];
q.push(e[t][i]);
bvis[e[t][i]]=1;
}
}
}
}
```
# 【模板】floyd
## 题目背景
模板题,无背景
## 题目描述
给出n个点,m条边的无向图,求每个点到其他点的距离之和%998244354的值
## 输入格式
第一行两个数n,m含义如上
从第二行开始,共m行,每行三个数x,y,l,代表从x到y点的长度为l
## 输出格式
n行,每行一个数,第i行代表点i到其他点的距离之和
## 样例 #1
### 样例输入 #1
```
2 1
1 2 4
```
### 样例输出 #1
```
4
4
```
## 样例 #2
### 样例输入 #2
```
4 5
1 2 1
1 3 2
2 3 2
3 4 3
2 4 4
```
### 样例输出 #2
```
8
7
7
12
```
## 提示
模板题,保证图联通
n<=500
m<=10000
1<=x,y<=n
l<=1e9
解题思路:floyd算法
完整代码如下:
```cpp
#include <bits/stdc++.h>
using namespace std;
const long long maxn=5005,mod=998244354,inf=0x3f3f3f3f;
long long d[maxn][maxn];
int main()
{
int n,m;
cin>>n>>m;
long long x,y,l;
for(int i=1; i<=n; i++){
for(int j=1; j<=n; j++){
d[i][j]=inf;
d[i][i]=0;
}
}//一个点与另一个点的距离为inf时,表示两点不相连
for(int i=1; i<=m; i++){
cin>>x>>y>>l;
d[x][y]=min(l,d[x][y]);
d[y][x]=min(l,d[y][x]);
}//邻接矩阵存无向图,只要存入最小距离即可
for(int k=1; k<=n; k++){
for(int i=1; i<=n; i++){
for(int j=1; j<=n; j++){
d[i][j]=min(d[i][j],d[i][k]+d[k][j]);
}
}
}//floyd算法,即算出每一点到其它点的最短距离
for(int i=1; i<=n; i++){
int sum=0;
for(int j=1; j<=n; j++){
if(d[i][j]!=inf) sum=(sum+d[i][j])%mod;
}
cout<<sum<<endl;
}
return 0;
}
```
# 【模板】单源最短路径(标准版)
## 题目背景
2018 年 7 月 19 日,某位同学在 [NOI Day 1 T1 归程](https://www.luogu.org/problemnew/show/P4768) 一题里非常熟练地使用了一个广为人知的算法求最短路。
然后呢?
100→60;
Ag→Cu;
最终,他因此没能与理想的大学达成契约。
小 F 衷心祝愿大家不再重蹈覆辙。
## 题目描述
给定一个n 个点,m 条有向边的带非负权图,请你计算从 s 出发,到每个点的距离。
数据保证你能从 s 出发到任意点。
## 输入格式
第一行为三个正整数 n, m, s。
第二行起 m 行,每行三个非负整数 u_i, v_i, w_i,表示从 u_i 到 v_i 有一条权值为 w_i 的有向边。
## 输出格式
输出一行 n 个空格分隔的非负整数,表示 s 到每个点的距离。
## 样例 #1
### 样例输入 #1
```
4 6 1
1 2 2
2 3 2
2 4 1
1 3 5
3 4 3
1 4 4
```
### 样例输出 #1
```
0 2 4 3
```
## 提示
样例解释请参考 [数据随机的模板题](https://www.luogu.org/problemnew/show/P3371)。
1 <= n <= 10^5;
1 <= m <= 2*10^5;
s = 1;
1 <= u_i, v_i<=n;
0 <= w_i <= 10 ^ 9,
0<=∑*w_i*<=10^9。
本题数据可能会持续更新,但不会重测,望周知。
解题思路:链式前向星存图,再用dijkstra算法的队列优化
注意: 存图时要从1号位开始,不要从0开始
完整代码如下:
```cpp
#include <bits/stdc++.h>
using namespace std;
const int maxn=1e6+5;
int head[maxn],cnt=1,dis[maxn],n,m,s;
bool vis[maxn];
struct ed{
int to,w,next;
}edge[maxn];
struct node{
int dis,u;
bool operator <(const node &a)const
{
return a.dis<dis;
}
};
priority_queue <node> q;
void add(int u,int v,int w);
void dijkstra();
int main()
{
cin>>n>>m>>s;
for(int i=1; i<=m; i++){
int u,v,w;
cin>>u>>v>>w;
add(u,v,w);
}//链式前向星存图
memset(dis,0x3f,sizeof(dis));//初始化距离
dijkstra();
for(int i=1; i<=n; i++) cout<<dis[i]<<" ";
return 0;
}
void add(int u,int v,int w)
{
edge[cnt].to=v;
edge[cnt].w=w;
edge[cnt].next=head[u];
head[u]=cnt++;
}
void dijkstra()
{
dis[s]=0;
q.push({0,s});
while(!q.empty()){
int u=q.top().u;
q.pop();
if(vis[u]) continue;
vis[u]=1;
for(int i=head[u]; i; i=edge[i].next){
int v=edge[i].to;
if(dis[v]>dis[u]+edge[i].w){
dis[v]=dis[u]+edge[i].w;
if(!vis[v]) q.push({dis[v],v});
}
}
}
}
```
Week9
最新推荐文章于 2024-05-21 23:16:53 发布