1 solutions

  • -13
    @ 2025-4-26 20:55:21

    因为lancas写的是lj题解看不懂 所以我来力🤓👆

    前面忘了后面忘了先输入

    cin >> n >> m;
    	for (int i = 1; i <= m; i++)
    	{
    		cin >> x >> y >> z;
    		a[x][y] = a[y][x] = z;
    	} 
    

    然后直接根据Floyd代码讲解写出一段求i~j的最短路径

    for (int k = 1; k <= n; k++) // k枚举两个点中间的转接点,
    		for (int i = 1; i <= n; i++) // i枚举起点
    			for (int j = 1; j <= n; j++) // j枚举重点
    				if (a[i][k] + a[k][j] < a[i][j]) // 如果走转接点更近的话就走转接点
    					a[i][j] = a[i][k] + a[k][j]; // 覆盖原来的
    

    之后我们发现它囊括了自环,但是这道题不用,所以需要重新覆盖一下对角线

    for (int i = 1; i <= n; i++)
    		a[i][i] = 0;
    

    最后输出

    for (int i = 1; i <= n; i++)
    	{
    		for (int j = 1; j <= n; j++)
    			cout << a[i][j] << " ";
    		cout << endl;
    	}
    

    然后你就会的到一坨错误的⑩

    为什么呢?

    因为a数组没有初始化

    为什么要初始化?

    因为我们需要对比谁更近,但是a数组默认全部都是0,所以一直都是最小的,我们怎么改都没法覆盖原来的0(

    所以我们需要先memset一下a数组,但是学memset的时候就说memset只能全部设为1、0、-1,那怎么办呢?

    这时候我们就需要使用16进制来进行

    所以

    const int INF = 0x3f3f3f3f; 
    // INF(0x3f3f3f3f) 是一个极巧妙的数,两个相加就是int的极限,两个相乘就是long long的极限
    // > h_h:用INT_MAX容易爆,所以用INF更好一点
    
    // ......
    
    memset(a, INF, sizeof(a));
    

    这时候提交就会得到一个100 Wrong Answer的东西

    h_h: 有重边

    仔细一看题目发现题目并没说没有重边,又结合题意需要求最小路径,于是我们就可以在输入时就处理这一情况,于是写出了:

    cin >> n >> m;
    	for (int i = 1; i <= m; i++)
    	{
    		cin >> x >> y >> z;
    		if (a[x][y] > z) // 如果旧路径比新路径长就覆盖较长的旧路径
    			a[x][y] = a[y][x] = z;
    	} 
    

    然后补上定义变量之类的我们就得到了完整版!


    完整代码

    #include <bits/stdc++.h>
    using namespace std;
    const int N = 1e3 + 10, INF = 0x3f3f3f3f;
    // INF(0x3f3f3f3f) 是一个极巧妙的数,两个相加就是int的极限,两个相乘就是long long的极限
    // > h_h:用INT_MAX容易爆,所以用INF更好一点
    
    int n, m, x, y, z, a[N][N]; // 定义变量
    
    int main()
    {
    	memset(a, INF, sizeof(a)); // 初始化
    	cin >> n >> m;
    	for (int i = 1; i <= m; i++)
    	{
    		cin >> x >> y >> z;
    		if (a[x][y] > z) // 如果旧路径比新路径长就覆盖较长的旧路径
    			a[x][y] = a[y][x] = z;
    	} 
    	
    	for (int k = 1; k <= n; k++) // k枚举两个点中间的转接点,
    		for (int i = 1; i <= n; i++) // i枚举起点
    			for (int j = 1; j <= n; j++) // j枚举重点
    				if (a[i][k] + a[k][j] < a[i][j]) // 如果走转接点更近的话就走转接点
    					a[i][j] = a[i][k] + a[k][j]; // 覆盖原来的
    	
    	for (int i = 1; i <= n; i++) // 覆盖对角线
    		a[i][i] = 0;
    	
    	for (int i = 1; i <= n; i++) // 输出
    	{
    		for (int j = 1; j <= n; j++)
    			cout << a[i][j] << " ";
    		cout << endl;
    	}
    	
    	return 0;
    }
    
  • 1

Information

ID
4652
Time
1000ms
Memory
512MiB
Difficulty
2
Tags
# Submissions
30
Accepted
13
Uploaded By