week 9

目录

 1.查找文献

题目

输入格式

输出格式

输入输出样例

 题解

代码

2.floyd

题目

输入格式

输出格式

输入输出样例

题解

代码 

3.单源最短路径(标准版)

题目

描述

输入格式

输出格式

输入输出样例

 题解

代码


 

 1.查找文献

题目

小K 喜欢翻看洛谷博客获取知识。每篇文章可能会有若干个(也有可能没有)参考文献的链接指向别的博客文章。小K 求知欲旺盛,如果他看了某篇文章,那么他一定会去看这篇文章的参考文献(如果他之前已经看过这篇参考文献的话就不用再看它了)。

假设洛谷博客里面一共有 n(n\le10^5)n(n≤105) 篇文章(编号为 1 到 nn)以及 m(m\le10^6)m(m≤106) 条参考文献引用关系。目前小 K 已经打开了编号为 1 的一篇文章,请帮助小 K 设计一种方法,使小 K 可以不重复、不遗漏的看完所有他能看到的文章。

这边是已经整理好的参考文献关系图,其中,文献 X → Y 表示文章 X 有参考文献 Y。不保证编号为 1 的文章没有被其他文章引用。

请对这个图分别进行 DFS 和 BFS,并输出遍历结果。如果有很多篇文章可以参阅,请先看编号较小的那篇(因此你可能需要先排序)。

输入格式

共 m+1m+1 行,第 1 行为 2 个数,nn 和 mm,分别表示一共有 n(n\le10^5)n(n≤105) 篇文章(编号为 1 到 nn)以及m(m\le10^6)m(m≤106) 条参考文献引用关系。

接下来 mm 行,每行有两个整数 X,YX,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加vector二维数组存图。

代码

#include<bits/stdc++.h>
using namespace std;
int n,m;
struct node{
	int u,v;
};
vector <int> v[100001];
vector <node> v1;
bool vis1[100001]={0},vis2[100001]={0};

bool cmp(node x,node y){
	if(x.v==y.v) return x.u<y.u;
	else return x.v<y.v;
}

void dfs(int x){
	vis1[x]=1;
	cout<<x<<" ";
	for(int i=0;i<v[x].size();i++){
		int xx = v1[v[x][i]].v;
		if(vis1[xx] == 0){
			dfs(xx);
		}
	}
}
void bfs(int x){
	queue <int> q;
	q.push(x);
	cout<<x<<" ";
	vis2[x]=1;
	while(!q.empty()){
		int a=q.front();
		for(int i=0;i<v[a].size();i++){
			int xx = v1[v[a][i]].v;
			if(vis2[xx] == 0){
				q.push(xx);
				cout<<xx<<" ";
				vis2[xx]=1;
			}
		}
		q.pop();
	}
}
int main(){
	cin>>n>>m;
	for(int i=0;i<m;i++){
		node no;
		cin>>no.u>>no.v;
		v1.push_back(no);
	}
	sort(v1.begin(),v1.end(),cmp);
	for(int i=0;i<m;i++)
		v[v1[i].u].push_back(i);
	dfs(1);
	cout<<endl;
	bfs(1);
}

2.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套模板,注意最后选择条件别写错就行

代码 

#include<bits/stdc++.h>
using namespace std;
long long  n,m;
long long f[600][600],ans[600];

int main(){
	cin>>n>>m;
	memset(f,0x3f,sizeof(f));
	for(int i=1;i<=m;i++){
		long long x,y,v;cin>>x>>y>>v;
		f[x][y]=min(v,f[x][y]);
		f[y][x]=min(v,f[y][x]);
	}
	for(int i=1;i<=n;i++){
        f[i][i] = 0;
	}
	for(int k=1;k<=n;k++){
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                f[i][j]=min(f[i][j],f[i][k]+f[k][j]);
            }
        }
    }

	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			ans[i]+=f[i][j];
		}
	}
	for(int i=1;i<=n;i++)
	cout<<ans[i]%998244354<<endl;
	return 0;
}

3.单源最短路径(标准版)

题目

2018 年 7 月 19 日,某位同学在 NOI Day 1 T1 归程 一题里非常熟练地使用了一个广为人知的算法求最短路。

然后呢?

100 \rightarrow 60100→60;

\text{Ag} \rightarrow \text{Cu}Ag→Cu;

最终,他因此没能与理想的大学达成契约。

小 F 衷心祝愿大家不再重蹈覆辙。

描述

给定一个 nn 个点,mm 条有向边的带非负权图,请你计算从 ss 出发,到每个点的距离。

数据保证你能从 ss 出发到任意点。

输入格式

第一行为三个正整数 n, m, sn,m,s。 第二行起 mm 行,每行三个非负整数 u_i, v_i, w_iui​,vi​,wi​,表示从 u_iui​ 到 v_ivi​ 有一条权值为 w_iwi​ 的有向边。

输出格式

输出一行 nn 个空格分隔的非负整数,表示 ss 到每个点的距离。

输入输出样例

输入 #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 

 题解

 Dijkstra,就是每次找一个dis 最小的点,边找便更新,最后输出就行。

代码

#include<bits/stdc++.h>
using namespace std;
int m,n,s;
int head[100000],cnt;
long long ans[1000000];
bool vis[1000000];

struct node{
	int to;
	int nextt;
	int wei;
}node[1000000];
struct priority{
    int ans;
    int id;
    bool operator <(const priority &x)const{
        return x.ans<ans;
    }
};

void add(int x,int y,int z){
	node[++cnt].to=y;
	node[cnt].wei=z;
	node[cnt].nextt=head[x];
	head[x]=cnt;
}

priority_queue<priority> q;

int main(){
	cin>>m>>n>>s;
	for(int i=1;i<=n;i++){
		ans[i]=2147483647;
	}
	ans[s]=0;
	for(int i=1;i<=n;i++){
		int a,b,c;
		cin>>a>>b>>c;
		add(a,b,c);
	}
	int u;
	q.push((priority){0,s});
    while(!q.empty()){
        priority temp=q.top();
        q.pop();
        u=temp.id;
        if(vis[u] == 0){
        	vis[u]=1;
	        for(int i=head[u];i;i=node[i].nextt){
	            int v = node[i].to;
	            if(ans[v] > ans[u] + node[i].wei){
	                ans[v]= ans[u] + node[i].wei;
	                if(vis[v] == 0){
	                    q.push((priority){ans[v],v});
	                }
	            }
	        }
		}
    }
	for(int i=1;i<=m;i++){
		cout<<ans[i]<<' ';
	}
}

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值