演算法訓練 最短路
問題描述
給定一個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;
}