圖結構練習——最短路徑(Dijkstra演算法)
阿新 • • 發佈:2019-01-02
think:
1注意重複邊的覆蓋
2注意map陣列的初始化
3注意dist陣列的初始化
圖結構練習——最短路徑
Time Limit: 1000MS Memory Limit: 65536KB
Problem Description
給定一個帶權無向圖,求節點1到節點n的最短路徑。
Input
輸入包含多組資料,格式如下。
第一行包括兩個整數n m,代表節點個數和邊的個數。(n<=100)
剩下m行每行3個正整數a b c,代表節點a和節點b之間有一條邊,權值為c。
Output
每組輸出佔一行,僅輸出從1到n的最短路徑權值。(保證最短路徑存在)
Example Input
3 2
1 2 1
1 3 1
1 0
Example Output
1
0
Hint
Author
趙利強
以下為accepted程式碼
#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;
#define INF 0x3f3f3f3f
int n, m;
int map[104][104], vis[104], dist[104];
void Dijkstra(int v)
{
int i, j, k;
for(i = 1; i <= n; i++)//dist陣列的初始化
{
dist[i] = map[v][i];
vis[i] = 0;
}
dist[v] = 0;
vis[v] = 1;
for(i = 0; i < n-1; i++)
{
int min = INF, u = v;
for(j = 1; j <= n; j++)//尋找未標記結點的最小值
{
if(vis[j] == 0 && dist[j] < min)
{
u = j;
min = dist[j];
}
}
vis[u] = 1 ;
for(k = 1; k <= n; k++)//更新最短路
{
if(vis[k] == 0 && map[u][k] < INF && dist[k] > dist[u] + map[u][k])
{
dist[k] = dist[u] + map[u][k];
}
}
}
}
int main()
{
int i, j, a, b, c;
while(scanf("%d %d", &n, &m) != EOF)
{
memset(vis, 0, sizeof(vis));
for(i = 1; i <= n; i++)
{
for(j = 1; j <= n; j++)
{
if(i == j)
map[i][j] = 0;
else
map[i][j] = INF;
}
}
for(i = 0; i < m; i++)
{
scanf("%d %d %d", &a, &b, &c);
if(map[a][b] > c)///避免覆蓋最短路
map[a][b] = map[b][a] = c;
}
if(m == 0)
printf("0\n");
else
{
Dijkstra(1);
printf("%d\n", dist[n]);
}
}
return 0;
}
/***************************************************
User name:
Result: Accepted
Take time: 12ms
Take Memory: 208KB
Submit time: 2017-02-17 19:30:41
****************************************************/
以下為wrong answer程式碼——Dijkstra演算法理解不紮實,導致變數位置使用錯誤(將u的位置寫成了v)
#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;
#define INF 0x3f3f3f3f
int n, m;
int map[104][104], vis[104], dist[104];
void Dijkstra(int v)
{
int i, j, k;
for(i = 1; i <= n; i++)//dist陣列的初始化
{
dist[i] = map[v][i];
vis[i] = 0;
}
dist[v] = 0;
vis[v] = 1;
for(i = 0; i < n-1; i++)
{
int min = INF, u = v;
for(j = 1; j <= n; j++)//尋找未標記結點的最小值
{
if(vis[j] == 0 && dist[j] < min)
{
u = j;
min = dist[j];
}
}
vis[u] = 1;
for(k = 1; k <= n; k++)//更新最短路
{
if(vis[k] == 0 && map[v][k] < INF && dist[k] > dist[u] + map[u][v])
{
dist[k] = dist[u] + map[u][k];
}
}
}
}
int main()
{
int i, j, a, b, c;
while(scanf("%d %d", &n, &m) != EOF)
{
memset(vis, 0, sizeof(vis));
for(i = 1; i <= n; i++)
{
for(j = 1; j <= n; j++)
{
if(i == j)
map[i][j] = 0;
else
map[i][j] = INF;
}
}
for(i = 0; i < m; i++)
{
scanf("%d %d %d", &a, &b, &c);
if(map[a][b] > c)///避免覆蓋最短路
map[a][b] = map[b][a] = c;
}
if(m == 0)
printf("0\n");
else
{
Dijkstra(1);
printf("%d\n", dist[n]);
}
}
return 0;
}
/***************************************************
User name:
Result: Wrong Answer
Take time: 16ms
Take Memory: 208KB
Submit time: 2017-02-17 19:27:15
****************************************************/
以下為wrong answer程式碼——
1 沒有考慮到重複邊的覆蓋問題
2 map陣列初始化錯誤
#include <stdio.h>
#include <string.h>
#define INF 9999999
int n, m;
int map[104][104], dist[10400], vis[10400];
void Dijkstra(int v)
{
for(int i = 1; i <= n; i++)
{
dist[i] = map[v][i];
vis[i] = 0;
}
vis[v] = 1;
dist[v] = 0;
for(int i = 0; i < n-1; i++)
{
int min = INF, u = v;
for(int j = 1; j <= n; j++)//尋找未訪問的結點中的最小值
{
if(vis[j] == 0 && dist[j] < min)
{
u = j;
min =dist[j];
}
}
vis[u] = 1;
for(int k = 1; k <= n; k++)//更新
{
if(vis[k] == 0 && map[u][k] < INF && dist[k] > dist[u] + map[u][k])
{
dist[k] = dist[u] + map[u][k];
}
}
}
}
int main()
{
int a, b, c;
while(scanf("%d %d", &n, &m) != EOF)
{
memset(map, 0, sizeof(map));
memset(vis, 0, sizeof(vis));
for(int i = 0; i < m; i++)
{
scanf("%d %d %d", &a, &b, &c);
map[a][b] = c;
}
Dijkstra(1);
printf("%d\n", dist[n]);
}
return 0;
}
/***************************************************
User name:
Result: Wrong Answer
Take time: 12ms
Take Memory: 192KB
Submit time: 2017-02-17 18:41:44
****************************************************/