1. 程式人生 > >演算法訓練 最短路

演算法訓練 最短路

問題描述

給定一個n個頂點,m條邊的有向圖(其中某些邊權可能為負,但保證沒有負環)。請你計算從1號點到其他點的最短路(頂點從1到n編號)。

輸入格式

第一行兩個整數n, m。

接下來的m行,每行有三個整數u, v, l,表示u到v有一條長度為l的邊。

輸出格式

共n-1行,第i行表示1號點到i+1號點的最短路。

樣例輸入

3 3
1 2 -1
2 3 -1
3 1 2

樣例輸出

-1
-2

資料規模與約定

對於10%的資料,n = 2,m = 2。

對於30%的資料,n <= 5,m <= 10。

對於100%的資料,1 <= n <= 20000,1 <= m <= 200000,-10000 <= l <= 10000,保證從任意頂點都能到達其他所有頂點。

這裡程式碼:記憶體過大

#include<iostream>
#include<cstring>
#define INF 99999
using namespace std;
int dp[20010][20010];
int view[20010];
int m=99999;
int path[20010];
int a;
int s=2;
void dfs(int cur, int dis)
{
    int i;
    if (s==cur) //判斷是否到達了目標城市
    {
        s++;
//        for (i = 1; i <= a; i++)     /// 輸出所有可能的路徑
//        {
//            if (path[i])
//            {
//                printf("%d ", path[i]); //輸出路徑
//            }
//        }
        cout<<dis<<endl;
        if (m > dis)  //更新最小路徑
        {
            m = dis;
        }
        return;
    }
    for (i=1;i<=a;++i)  
    {
        if (dp[cur][i]!=INF&&view[i]==0)
        {
            view[i]=1;
            path[i]=i;
            dfs(i,dis+dp[cur][i]);
            view[i]=0;       
            path[i]=0;
        }
    }
}
int main()
{
    memset(dp,0,sizeof(dp));
    memset(view,0,sizeof(view));
    int b,u,v,l;
    cin>>a>>b;
    for(int i=1;i<=a;i++)
    for(int j=1;j<=a;j++)
    {
        if(i==j)
        dp[i][j]=0;
        else
        dp[i][j]=INF;
    }
    for(int i=1;i<=b;i++)
    {
        cin>>u>>v>>l;
        dp[u][v]=dp[v][u]=l;
    }
    view[1]=1;
    path[1]=1;
    for(int i=2;i<=b;i++)
    dfs(1,0);
    return 0;
}

改進後:

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
const int MAXN = 20001;
int floyd[MAXN][MAXN];
int main(){
    int m, n;
    memset(floyd, 2, sizeof(floyd));
    cin >> m >> n;
    for (int i = 1; i <= m; i++){
        int from, to, value;
        cin >> from >> to >> value;
        floyd[from][to] = value;
    }
    for (int j = 1; j <= n; j++)
        for (int k = 1; k <= n; k++){
            if (floyd[1][k] + floyd[k][j] < floyd[1][j])
                floyd[1][j] = floyd[1][k] + floyd[k][j];
        }
    for (int m = 2; m <= n; m++)
        cout << floyd[1][m] << endl;
    return 0;
    }