HDU 2112 HDU Today

传送门

最短路。很坑的是,这道题没说清楚是不是有向边(其实是无向边),而且还有起点和终点相同的数据。

两年前我写的是一个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;
}
posted @ 2019-03-23 16:55  CrossingOver  阅读(250)  评论(0编辑  收藏  举报