1.题目描述:
2.题意概述:
给出n,m,s,t,n表示有n个点,m表示有m条边,然后给出m行数据表示m条边,每条边的数据有连接两点的序号以及该边的权值,问说从点s到点t的最短路径是多少。
3.解题思路:
分析题目的样列可知,这一题是要用邻接矩阵来存储无向图,所以要注意无向图怎么存储在邻阶表。连接表的横列有N项,纵列也是N项。形成的N*N项每项都被称为边结点,每项都有纵横两个坐标,例如点(N,N-1),表示的就是从第N点向第N-1点有无路径。由于有E条边,自然有E条路径,但是由于无向=双向,所以要乘以2
4.AC代码:
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define maxn 20100
#define N 111
#define eps 1e-6
#define pi acos(-1.0)
#define e exp(1.0)
using namespace std;
const int mod = 1e9 + 7;
typedef long long ll;
typedef unsigned long long ull;
struct node
{
int to, val;
node(int a, int b) { to = a; val = b; }
};
vector<node> mp[maxn];
int dis[maxn];
bool vis[maxn];
void spfa(int sta, int n)
{
memset(vis, 0, sizeof(vis));
fill(dis, dis + n + 1, INF);
deque<int> q;
dis[sta] = 0;
vis[sta] = 1;
q.push_back(sta);
while (!q.empty())
{
int u = q.front();
q.pop_front();
vis[u] = 0;
int sz = mp[u].size();
for (int i = 0; i < sz; i++)
{
int v = mp[u][i].to;
int val = mp[u][i].val;
if (dis[v] > dis[u] + val)
{
dis[v] = dis[u] + val;
if (!vis[v])
{
vis[v] = 1;
if (!q.empty() && dis[v] >= dis[q.front()])
q.push_front(v);
else
q.push_back(v);
}
}
}
}
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
long _begin_time = clock();
#endif
int t;
scanf("%d", &t);
for (int i = 1; i <= t; i++)
{
int n, m, s, t;
scanf("%d%d%d%d", &n, &m, &s, &t);
for (int i = 0; i < n; i++)
mp[i].clear();
while (m--)
{
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
mp[u].push_back(node(v, w));
mp[v].push_back(node(u, w));
}
spfa(s, n);
printf("Case #%d: ", i);
if (dis[t] != INF)
printf("%d\n", dis[t]);
else
puts("unreachable");
}
#ifndef ONLINE_JUDGE
long _end_time = clock();
printf("time = %ld ms.", _end_time - _begin_time);
#endif
return 0;
}