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名选手的排名仍无法确定。
难度 一星