c++练习_Floyd简介(弗洛伊德算法)

1,Floyd简介

Floyd BFS 实现无权最短路 (BFS局限性:无权) 最短路问题: 确定起点 确定终点 起点和终点都确定 全局最短路 Floyd 弗洛伊德算法 多源汇最短路,边权为负(不允许出现负权环) 时间复杂度是 O(n^3)

核心:如果发现两个点之间可以通过一个中转点中转,使得两点之间的路径变得更短,此时两个点之间 需要添加中转点才能获得最短路径。

一般处理步骤:

#include <iostream>

using namespace std;

   <1.定义>

int dp[105][105];          <dp[i][j]表示i点到j点的最短路径>

int main(){

    <2.初始化dp数组>

    <3.根据输入的信息 更新最短路径 假设存在一条无向边u到v的权值为w dp[u][v]=dp[v][u]=w;>

    <4.Floyd更新最短路径>

    <5.输出>

    return 0;
}

弗洛伊德算法练习 

1.

【模板】Floyd 算法

题目描述

给出一张由 n 个点 m 条边组成的无向图。

求出所有点对 (i,j) 之间的最短路径。

输入格式

第一行为两个整数 n,m,分别代表点的个数和边的条数。

接下来 m 行,每行三个整数 u,v,w,代表 u,v 之间存在一条边权为 w 的边。

输出格式

输出 n 行每行 n 个整数。

第 i 行的第 j 个整数代表从 i 到 j 的最短路径。

样例 #1

样例输入 #1

4 4
1 2 1
2 3 1
3 4 1
4 1 1

样例输出 #1

0 1 2 1
1 0 1 2
2 1 0 1
1 2 1 0

提示

对于 100%100% 的数据,�≤100,�≤4500n≤100,m≤4500,任意一条边的权值 �w 是正整数且 1⩽�⩽10001⩽w⩽1000。

#include<iostream>
using namespace std;
int dp[1005][1005];
int main(){
	int n,m,u,v,w;
	cin>>n>>m;
	for(int i=1;i<=m;i++){
		cin>>u>>v>>w;		
		dp[u][v]=w;
		dp[v][u]=w;
		//cout<<dp[u][v]<<endl;
	}
	
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			if(i!=j){
				if (dp[i][j]==0) {
					dp[i][j] = 999999999;
				};
			}
		}
	}
	for(int k=1;k<=n;k++){
		for(int i=1;i<=n;i++){
			for(int j=1;j<=n;j++){
				dp[i][j]=min(dp[i][j],dp[i][k]+dp[k][j]);
			}
		}
	}
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			cout<<dp[i][j]<<" ";
		}
		cout<<endl;
	}
	
	return 0;
}

难度  一星

2,

Clear And Present Danger S

题目描述

农夫约翰正驾驶一条小艇在牛勒比海上航行.

海上有 (1≤100)N(1≤N≤100) 个岛屿,用 11 到 N 编号.约翰从 11 号小岛出发,最后到达 N 号小岛.

一张藏宝图上说,如果他的路程上经过的小岛依次出现了 A1​,A2​,…… ,AM​(2≤M≤10000) 这样的序列(不一定相邻),那他最终就能找到古老的宝藏. 但是,由于牛勒比海有海盗出没.约翰知道任意两个岛屿之间的航线上海盗出没的概率,他用一个危险指数 (Di,j​(0≤Di,j​≤100000)来描述.他希望他的寻宝活动经过的航线危险指数之和最小.那么,在找到宝藏的前提下,这个最小的危险指数是多少呢?

输入格式

第一行:两个用空格隔开的正整数 N 和 M。

第二到第 M+1 行:第 i+1 行用一个整数 Ai​ 表示 FJ 必须经过的第 i 个岛屿

第 M+2 到第 N+M+1 行:第 i+M+1 行包含 N 个用空格隔开的非负整数分别表示 i 号小岛到第 1……N 号小岛的航线各自的危险指数。保证第 i 个数是 00。

输出格式

第一行:FJ 在找到宝藏的前提下经过的航线的危险指数之和的最小值。

样例 #1

样例输入 #1

3 4 
1 
2 
1 
3 
0 5 1 
5 0 2 
1 2 0 

样例输出 #1

7

提示

说明
这组数据中有三个岛屿,藏宝图要求 FJ 按顺序经过四个岛屿:11 号岛屿、22 号岛屿、回到 11 号岛屿、最后到 33 号岛屿。每条航线的危险指数也给出了:航路(1,2),(2,3),(3,1)(1,2),(2,3),(3,1) 和它们的反向路径的危险指数分别是 5,2,15,2,1。

FJ 可以通过依次经过 1,3,2,3,1,31,3,2,3,1,3 号岛屿以 77 的最小总危险指数获得宝藏。这条道路满足了奶牛地图的要求 (1,2,1,3)(1,2,1,3)。我们避开了 11 号和 22 号岛屿之间的航线,因为它的危险指数太大了。

注意:测试数据中 a 到 b 的危险指数不一定等于 b 到 a 的危险指数!

#include<bits/stdc++.h>
using namespace std;
int d[105][105],a[10005],n,m,ans=0;
int main(){
	cin>>n>>m;
	for(int i=1;i<=m;i++){
		cin>>a[i];
	}
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			cin>>d[i][j];
		}
	}
	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][k]+d[k][j],d[i][j]);
			}
		}
	}
	ans=d[1][a[1]];
	for(int i=2;i<=m;i++){
		ans+=d[a[i-1]][a[i]];
	}
	ans+=d[a[m]][n];
	cout<<ans;
	return 0;
}

难度  二星

思考题:

选手对决

题目描述

N(1 <= N <= 100)名选手们最近参加了场程序设计竞赛。在赛场上,选手们按1…N依次编号。每名选手的编程能力不尽相同,并且没有哪两名选手的水平不相上下,也就是说,选手们的编程能力有明确的排名。 整个比赛被分成了若干轮,每一轮是两名指定编号的选手的对决。如果编号为A的选手的编程能力强于编号为B的选手(1 <= A <= N; 1 <= B <= N; A != B) ,那么她们的对决中,编号为A的选手总是能胜出。 现在裁判想知道选手们编程能力的具体排名,于是他找来了选手们所有 M(1 <= M <= 4,500)轮比赛的结果,希望你能根据这些信息,推断出尽可能多的选手的编程能力排名。比赛结果保证不会自相矛盾。

输入格式

第1行: 2个用空格隔开的整数:N 和 M

第2…M+1行: 每行为2个用空格隔开的整数A、B,描述了参加某一轮比赛的选手的编号,以及结果(编号为A,即为每行的第一个数的选手为 胜者)

输出格式

第1行: 输出1个整数,表示排名可以确定选手排名的数目

样例 #1

样例输入 #1

5 5
4 3
4 2
3 2
1 2
2 5

样例输出 #1

2

提示

输出说明:

编号为2的选手输给了编号为1、3、4的选手,也就是说她的水平比这3名选手都差。

而编号为5的选手又输在了她的手下,也就是说,她的水平比编号为5的选手强一些。

于是,编号为2的选手的排名必然为第4,编号为5的选手的水平必

然最差。其他3名选手的排名仍无法确定。

难度 一星

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值