Acwing 4074. 铁路与公路 java 弗洛伊德 脑经急转弯
🤠 原题地址
👨🏫 两车不能同时到达除 1 和 n 的城市,虚晃一枪,故意误导的,输入铁路,没铁路才有公路,并不会冲突,并且 1 ~ n 必有一条直达路 (公 / 铁),O(1)解决一台车的最短路问题
👨🏫 弗洛伊德
① 核心:以每个点为 中间人 试图去 拉近它的 两邻居的距离
② 遍历每一个点,遍历每一个入度,遍历每一个出度
🐷 O( n^3 )
import java.io.*;
import java.util.*;
public class Main
{
static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
static BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out));
static int N = 410, n, m;
static int[][] g = new int[N][N];
static int[][] f = new int[N][N];// 铁路邻接矩阵
static int[][] d = new int[N][N];
public static void main(String[] args) throws IOException
{
String[] split = in.readLine().split(" ");
n = Integer.parseInt(split[0]);
m = Integer.parseInt(split[1]);
// 初始化邻接矩阵
for (int i = 0; i < f.length; i++)
Arrays.fill(f[i], 0x3f3f3f3f);
for (int i = 0; i < g.length; i++)
Arrays.fill(g[i], 0x3f3f3f3f);
// 输入铁路
for (int i = 0; i < m; i++)
{
String[] split2 = in.readLine().split(" ");
int a = Integer.parseInt(split2[0]);
int b = Integer.parseInt(split2[1]);
f[a][b] = f[b][a] = 1;
}
// 自行补充公路
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
if (f[i][j] != 1 && i != j)
g[i][j] = 1;
int res = Math.max(floyd(f), floyd(g));
if (res == 0x3f3f3f3f)
res = -1;
out.write(res + "");
out.flush();
}
private static int floyd(int[][] d)
{
for (int k = 1; k <= n; k++)
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
d[i][j] = Math.min(d[i][j], d[i][k] + d[k][j]);
return d[1][n];
}
}
👨🏫 dijkstra O( n^2 )
import java.io.*;
import java.util.*;
public class Main
{
static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
static BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out));
static int N = 410, n, m;
static int[][] g = new int[N][N];
static int[][] f = new int[N][N];// 铁路邻接矩阵
static int[] dist = new int[N];
static boolean[] st = new boolean[N];
public static void main(String[] args) throws IOException
{
String[] split = in.readLine().split(" ");
n = Integer.parseInt(split[0]);
m = Integer.parseInt(split[1]);
// 初始化邻接矩阵
for (int i = 0; i < f.length; i++)
Arrays.fill(f[i], 0x3f3f3f3f);
for (int i = 0; i < g.length; i++)
Arrays.fill(g[i], 0x3f3f3f3f);
// 输入铁路
for (int i = 0; i < m; i++)
{
String[] split2 = in.readLine().split(" ");
int a = Integer.parseInt(split2[0]);
int b = Integer.parseInt(split2[1]);
f[a][b] = f[b][a] = 1;
}
// 自行补充公路
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
if (f[i][j] != 1 && i != j)
g[i][j] = 1;
int a = dijkstra(f);
int b = dijkstra(g);
if (a == -1 || b == -1)
System.out.println(-1);
else
System.out.println(Math.max(a, b));
}
private static int dijkstra(int[][] a)
{
if (a[1][n] == 1)
return 1;
// 重复使用的记得要初始化
Arrays.fill(dist, 0x3f3f3f3f);
Arrays.fill(st, false);
dist[1] = 0;
for (int i = 0; i < n - 1; i++)
{
int t = -1;
// 求出到当前已知最短路的 集合 距离最近 的节点
for (int j = 1; j <= n; j++)
if (!st[j] && (t == -1 || dist[j] < dist[t]))
t = j;
st[t] = true;
for (int j = 1; j <= n; j++)
dist[j] = Math.min(dist[j], dist[t] + a[t][j]);
}
if (dist[n] == 0x3f3f3f3f)
return -1;
else
return dist[n];
}
}