题干:

HDU Today

Time Limit : 15000/5000ms (Java/Other)   Memory Limit : 32768/32768K (Java/Other)

Total Submission(s) : 11   Accepted Submission(s) : 5

Problem Description

经过锦囊相助,海东集团终于度过了危机,从此,HDU的发展就一直顺风顺水,到了2050年,集团已经相当规模了,据说进入了钱江肉丝经济开发区500强。这时候,XHD夫妇也退居了二线,并在风景秀美的诸暨市浬浦镇陶姚村买了个房子,开始安度晚年了。
这样住了一段时间,徐总对当地的交通还是不太了解。有时很郁闷,想去一个地方又不知道应该乘什么公交车,在什么地方转车,在什么地方下车(其实徐总自己有车,却一定要与民同乐,这就是徐总的性格)。
徐总经常会问蹩脚的英文问路:“Can you help me?”。看着他那迷茫而又无助的眼神,热心的你能帮帮他吗?
请帮助他用最短的时间到达目的地(假设每一路公交车都只在起点站和终点站停,而且随时都会开)。

 

Input

输入数据有多组,每组的第一行是公交车的总数N(0<=N<=10000);
第二行有徐总的所在地start,他的目的地end;
接着有n行,每行有站名s,站名e,以及从s到e的时间整数t(0<t<100)(每个地名是一个长度不超过30的字符串)。
note:一组数据中地名数不会超过150个。
如果N==-1,表示输入结束。

Output

如果徐总能到达目的地,输出最短的时间;否则,输出“-1”。

Sample Input

6
xiasha westlake
xiasha station 60
xiasha ShoppingCenterofHangZhou 30
station westlake 20
ShoppingCenterofHangZhou supermarket 10
xiasha supermarket 50
supermarket westlake 10
-1

Sample Output

50

Hint: The best route is: xiasha->ShoppingCenterofHangZhou->supermarket->westlake 虽然偶尔会迷路,但是因为有了你的帮助 **和**从此还是过上了幸福的生活。 ――全剧终――

解题报告:

    几乎裸题单源最短路,加一个判断两者是否可达即可。(可用并查集也可用dis[v] = INF)

    字符串用map映射成一个整数即可。

AC代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<map>
#include<iostream>
using namespace std;
const int MAX = 100000 + 5;
const int INF = 0x3f3f3f3f ;
map<string,int> mp; 
struct Node {
	int to;
	int w;
	int ne;
//	bool operator <(const Node & b) const {
//		return w>b.w;
//	}
} e[MAX];

struct point {
	int pos;
	int c;
	point(){}//没有此构造函数不能写  node t  这样
	point(int pos,int c):pos(pos),c(c){}//可以写node(pos,cost)这样
	bool operator <(const point & b) const {
		return c>b.c;
	}
};

int head[MAX];
int vis[MAX];
int cnt = 0;
int n,m;
int top = -1;
int dis[MAX];//表示从出发点开始到该点的最短距离。 
void add(int u,int v,int w) {
	e[cnt].to = v;
	e[cnt].w = w;
	e[cnt].ne = head[u];
	head[u] = cnt;
	cnt++;
}
void Dijkstra(int u,int v) {
	priority_queue<point> pq; 
	dis[u] = 0;
	point cur = point(u,0);
	pq.push(cur);
//	vis[u] = 1;
	while(!pq.empty()) {
		point now = pq.top();pq.pop();
		if(vis[now.pos] == 1) continue;
		vis[now.pos] = 1;
		if(now.pos == v) break;//不把这一步放到 if(vis[now.pos] == 1) continue; 的原因是:要记录成v也是走过的,这样方便统一。 
		for(int i = head[now.pos]; i!=-1; i=e[i].ne) {
			if(  dis[e[i].to] > dis[now.pos] + e[i].w ) {
				dis[e[i].to] = dis[now.pos] + e[i].w;
				pq.push(point(e[i].to,dis[e[i].to] ) );	
			}
		} 
	}
	if(dis[v] == INF) {
		printf("-1\n");
	}
	else  printf("%d\n",dis[v]);
	
} 
void init() {
	cnt = 0;top = -1;
	mp.clear();
	memset(head,-1,sizeof(head) );
	memset(dis,INF,sizeof(dis) ) ;
	memset(vis,0,sizeof(vis) ) ;
}
int main()
{
	
	int a,b,w;
	char st[40],ed[40];
	char u[40],v[40];
	while(~scanf("%d",&n) ) {
		if(n == -1) break;
		init();
		scanf("%s %s",st,ed);
		if(mp.find(st) == mp.end() ) mp[st] = ++top;
		if(mp.find(ed) == mp.end() ) mp[ed] = ++top;
		for(int i = 1; i<=n; i++) {
			scanf("%s %s %d",&u,&v,&w);
			if(mp.find(u) == mp.end() ) mp[u] = ++top;
			if(mp.find(v) == mp.end() ) mp[v] = ++top;
			
			add(mp[u],mp[v],w);add(mp[v],mp[u],w);
		}
		Dijkstra(mp[st],mp[ed]);//或者 Dijkstra(0,1)
	}
	
	return 0 ;
 }