今天来水题-_-
time:2025-02-08
B3647 【模板】Floyd
题目描述
给出一张由 n 个点 m 条边组成的无向图。
求出所有点对 (i,j) 之间的最短路径。
输入格式
第一行为两个整数 n,m,分别代表点的个数和边的条数。
接下来 m 行,每行三个整数 u,v,w 代表 u,v 之间存在一条边权为 w 的边。
输出格式
输出 nn 行每行 nn 个整数。
第 i 行的第 j 个整数代表从 i 到 j 的最短路径。
输入输出样例
输入 #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% 的数据,n≤100n≤100,m≤4500m≤4500,任意一条边的权值 ww 是正整数且 1⩽w⩽10001⩽w⩽1000。
数据中可能存在重边。
WA(hack数据wa)代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int n, m;
int dist[10000][10000];
void solve()
{
cin >> n >> m;
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
if (i != j)
dist[i][j] = INT_MAX;
for (int i = 0; i < m; i++)
{
int u, v , w;
cin >> u >> v >> w;
dist[u - 1][v - 1] = w;
dist[v - 1][u - 1] = w;
}
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
for (int k = 0; k < n; k++)
if (dist[j][i] != INT_MAX && dist[i][k] != INT_MAX)
dist[j][k] = min(dist[j][k], dist[j][i] + dist[i][k]);
for (int i = 0; i < n; i++, cout << endl)
for (int j = 0; j < n; j++)
cout << dist[i][j] << " ";
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int t = 1;
// cin >> t;
while (t--)
solve();
return 0;
}
WA问题
重边没有考虑到!
例:
方框中A至D有两条边,不一样。
这事就有小伙伴们问了:为什么不一样呢?这不是平面几何。
(题目是无向图)
错误代码
for (int i = 0; i < m; i++)
{
int u, v , w;
cin >> u >> v >> w;
//下面出了问题
dist[u - 1][v - 1] = w;
dist[v - 1][u - 1] = w;
}
如果a到b有两条边,那么系统默认第二条,导致出错。
AC代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int n, m;
int dist[10000][10000];
void solve()
{
cin >> n >> m;
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
if (i != j)
dist[i][j] = INT_MAX;
for (int i = 0; i < m; i++)
{
int u, v , w;
cin >> u >> v >> w;
dist[u - 1][v - 1] = min(dist[u - 1][v - 1], w);
dist[v - 1][u - 1] = min(dist[v - 1][u - 1], w);
}
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
for (int k = 0; k < n; k++)
if (dist[j][i] != INT_MAX && dist[i][k] != INT_MAX)
dist[j][k] = min(dist[j][k], dist[j][i] + dist[i][k]);
for (int i = 0; i < n; i++, cout << endl)
for (int j = 0; j < n; j++)
cout << dist[i][j] << " ";
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int t = 1;
// cin >> t;
while (t--)
solve();
return 0;
}
AC思路
创建一个邻接表,全设为无穷大(INT_MAX)输入之后进行O(n^3)的循环,i是中转点,j和k分别是起点和终点。i判断增加中转点是否比原路更近↓
if (dist[j][i] != INT_MAX && dist[i][k] != INT_MAX)
dist[j][k] = min(dist[j][k], dist[j][i] + dist[i][k]);