最短路。很坑的是,这道题没说清楚是不是有向边(其实是无向边),而且还有起点和终点相同的数据。
两年前我写的是一个map<string,int>
和一个vector<string>
来对地名和下标双向关联,但是现在发现没必要了,只用一个map<string,int>
用来查重就行了,如果让你输出地名之类的才可能需要双向关联。
#include <iostream>
#include <algorithm>
#include <vector>
#include <cstring>
#include <map>
#include <string>
using namespace std;
const int MAXN = 152;
const int INF = 1e9;
int M, S, T;
map<string, int> m;
int g[MAXN][MAXN];
int dis[MAXN];
bool vis[MAXN];
int cnt;
void init()
{
memset(g, -1, sizeof g);
m.clear();
memset(vis, 0, sizeof vis);
fill(dis, dis + MAXN, INF);
cnt = 0;
}
void dijkstra(int s)
{
dis[s] = 0;
for (int i = 0; i < cnt; i++)
{
int u = -1, mind = INF;
for (int j = 0; j < cnt; j++)
{
if (!vis[j] && dis[j] < mind)
{
mind = dis[j];
u = j;
}
}
if (u == -1) return;
vis[u] = 1;
for (int j = 0; j < cnt; j++)
{
if (!vis[j] && g[u][j] != -1)
{
if (dis[u] + g[u][j] < dis[j])
dis[j] = dis[u] + g[u][j];
}
}
}
}
int main()
{
string a, b; // 如果地名带空格怎么办?
int w;
for (; ~scanf("%d", &M);)
{
if (M == -1) return 0;
init();
cin >> a >> b;
if (a == b) // 好无聊啊,还会有起始终止相同的情况
{
//printf("0\n");
//break; 还真不能直接退,因为要等它输入完那几个公交车
m.insert(make_pair(a, S = T = cnt++));
}
else
{
m.insert(make_pair(a, S = cnt++));
m.insert(make_pair(b, T = cnt++));
}
for (; M--;)
{
cin >> a >> b >> w;
if (m.find(a) == m.end())
m.insert(make_pair(a, cnt++));
if (m.find(b) == m.end())
m.insert(make_pair(b, cnt++));
int aid = m[a];
int bid = m[b];
if (g[aid][bid] == -1) g[aid][bid] = g[bid][aid] = w; // 公交车是往返开的
else g[aid][bid] = g[bid][aid] = min(g[aid][bid], w);
}
dijkstra(S);
if (dis[T] != INF) printf("%d\n", dis[T]);
else printf("-1\n");
}
return 0;
}