P5318 【深基18.例3】查找文献
小K 喜欢翻看洛谷博客获取知识。每篇文章可能会有若干个(也有可能没有)参考文献的链接指向别的博客文章。小K 求知欲旺盛,如果他看了某篇文章,那么他一定会去看这篇文章的参考文献(如果他之前已经看过这篇参考文献的话就不用再看它了)。
假设洛谷博客里面一共有 n(n≤10^5) 篇文章(编号为 1 到 n)以及m(m≤10^6) 条参考文献引用关系。目前小 K 已经打开了编号为 1 的一篇文章,请帮助小 K 设计一种方法,使小 K 可以不重复、不遗漏的看完所有他能看到的文章。
这边是已经整理好的参考文献关系图,其中,文献 X → Y 表示文章 X 有参考文献 Y。不保证编号为 1 的文章没有被其他文章引用。
请对这个图分别进行 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
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它,所以,我就先正常存图进去,然后再对图进行dfs和bfs;题目也提示了我们要对其进行排序,我们就对sort函数进行一个cmp的重置;
#include <bits/stdc++.h>
using namespace std;
struct edge{
int u,v;//u为起点,v为终点
};
int n,m;
vector<int> q[100005];
bool vis1[100005],vis2[100005];//vis1用于dfs,vis2用于bfs
vector<edge> s;
bool cmp(edge a,edge b){//先看编号较小的文献
if(a.v==b.v) return a.u<b.u;
else return a.v<b.v;//小于号从大到小排序
}
void dfs(int k){
vis1[k]=1;
cout<<k<<' ';
for(int i=0;i<q[k].size();i++){
if(!vis1[s[q[k][i]].v]){
dfs(s[q[k][i]].v);//因为只需要dfs一次,所以就懒得重置vis1数组了
}
}
}
void bfs(int h){
queue<int> p;
p.push(h);
cout<<h<<' ';
vis2[h]=1;
while(!p.empty()){
int qd=p.front();
for(int i=0;i<q[qd].size();i++){
int zd=s[q[qd][i]].v;
if(!vis2[zd]){
p.push(zd);
cout<<zd<<' ';
vis2[zd]=1;
}
}
p.pop();
}
}
int main(){
cin>>n>>m;
for(int i=0;i<m;i++){
int u1,v1;
cin>>u1>>v1;
s.push_back((edge){u1,v1});
}
sort(s.begin(),s.end(),cmp);
for(int i=0; i<m;i++){
q[s[i].u].push_back(i);//存图 ,对于起点,数组存下它的对应的终点
}
dfs(1);
cout<<endl;
bfs(1);
return 0;
}
U80592 【模板】floyd
题目背景
模板题,无背景
题目描述
给出n个点,m条边的无向图,求每个点到其他点的距离之和%998244354的值
输入格式
第一行两个数n,m含义如上 从第二行开始,共m行,每行三个数x,y,l,代表从x到y点的长度为l
输出格式
n行,每行一个数,第i行代表点i到其他点的距离之和
输入输出样例
输入 #1
2 1 1 2 4
输出 #1
4
4
输入 #2
4 5 1 2 1 1 3 2 2 3 2 3 4 3 2 4 4
输出 #2
8 7 7 12
首先更具题目得知,这是一个无向图;
我们先对无向图进行存图;
这边是一个floyd算法
而算法的具体思想为:
1 .邻接矩阵(二维数组)dist储存路径,数组中的值开始表示点点之间初始直接路径,最终是点点之间的最小路径,有两点需要注意的,第一是如果没有直接相连的两点那么默认为一个很大的值(不要因为计算溢出成负数),第二是自己和自己的距离要为0。
2 .从第1个到第n个点依次加入松弛计算,每个点加入进行试探枚举是否有路径长度被更改(自己能否更新路径)。顺序加入(k枚举)松弛的点时候,需要遍历图中每一个点对(i,j双重循环),判断每一个点对距离是否因为加入的点而发生最小距离变化,如果发生改变(变小),那么两点(i,j)距离就更改。
dp[i][j]=min(dp[i][j],dp[i][k]+dp[k][j])
#include <bits/stdc++.h>
#define int long long
using namespace std;
int maxx=0x3f3f3f3f,f[5001][5001];
const int mod=99824435;
signed main(){
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
f[i][j]=maxx;
f[i][i]=0;
}
}
for(int i=1;i<=m;i++){
int x,y,l;
cin >> x >> y >> l;
f[x][y]=min(l,f[x][y]);
f[y][x]=min(l,f[y][x]);
}
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(f[i][k]+f[k][j]<f[i][j])
f[i][j]=(f[i][k]+f[k][j]);
for(int i=1;i<=n;i++){
int sum=0;
for(int j=1;j<=n;j++)
if(f[i][j]!=maxx) sum=(sum+f[i][j])%mod;
cout<<sum<<endl;
}
return 0;
}
P4779 【模板】单源最短路径(标准版)
题目背景
2018 年 7 月 19 日,某位同学在 NOI Day 1 T1 归程 一题里非常熟练地使用了一个广为人知的算法求最短路。
然后呢?
100→60;
Ag→Cu;
最终,他因此没能与理想的大学达成契约。
小 F 衷心祝愿大家不再重蹈覆辙。
题目描述
给定一个 n 个点,m 条有向边的带非负权图,请你计算从 s 出发,到每个点的距离。
数据保证你能从 s 出发到任意点。
输入格式
第一行为三个正整数n,m,s。 第二行起 m 行,每行三个非负整数ui,vi,wi,表示从 ui 到 vi 有一条权值为 wi 的有向边。
输出格式
输出一行 n 个空格分隔的非负整数,表示 s 到每个点的距离。
输入输出样例
输入 #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
这题是一题我不会的题...
看了别人的题解,但也把它的做法优化了一下
把他的for循环改成了while循环...
就是菜,还得练
#include <bits/stdc++.h>
using namespace std;
struct Edge{
int to,len;
};
int n,m,s,u,v,w;
vector<list<Edge> > dis;
struct Dot{
int dist,t;
bool operator < (Dot a)const{
return dist>a.dist;//重载运算符
}
};
priority_queue<Dot> q;
vector<int> f;
int total;
int main(){
cin>>n>>m>>s;
dis.reserve(n+1);
f.reserve(n+1);
for(int i=0;i<=n;i++)
dis.push_back(list<Edge>());
for(int i=1;i<=m;i++){
cin>>u>>v>>w;
if(u!=v) dis[u].push_back( {v,w} );
}
for(int i=0;i<=n;i++)
f.push_back(2147483647);
q.push( Dot{0,s} );
total=n;
while(total>0&&!q.empty()){
Dot now=q.top(); q.pop();
if(f[now.t]<=now.dist) continue;
f[now.t]=now.dist; total--;
for(list<Edge>::const_iterator i=dis[now.t].begin();i!=dis[now.t].end();i++)
q.push( Dot{now.dist+i->len,i->to} );
}
for(int i=1;i<n;i++) cout<<f[i]<<' ';
cout<<f[n]<<endl;
return 0;
}