1031. Campus
Constraints
Time Limit: 1 secs, Memory Limit: 32 MB
Description
At present, Zhongshan University has 4 campuses with a total area of 6.17 square kilometers sitting respectively on both sides of the Pearl River or facing the South China Sea. The Guangzhou South Campus covers an area of 1.17 square kilometers, the North Campus covers an area of 0.39 square kilometers, the Guangzhou East Campus has an area of 1.13 square kilometers and the Zhuhai Campus covers an area of 3.48 square kilometers. All campuses have exuberance of green trees, abundance of lawns and beautiful sceneries, and are ideal for molding the temperaments, studying and doing research.
![](http://soj.sysu.edu.cn/UserFiles/zsucpc_pic2.jpg)
Sometime, the professors and students have to go from one place to another place in one campus or between campuses. They want to find the shortest path between their source place S and target place T. Can you help them?
Input
The first line of the input is a positive integer C. C is the number of test cases followed. In each test case, the first line is a positive integer N (0<N<=100) that represents the number of roads. After that, N lines follow. The i-th(1<=i<=N) line contains two strings Si, Ti and one integer Di (0<=Di<=100). It means that there is a road whose length is Di between Si and Ti. Finally, there are two strings S and T, you have to find the shortest path between S and T. S, T, Si(1<=i<=N) and Ti(1<=i<=N) are all given in the following format: str_Campus.str_Place. str_Campus represents the name of the campus, and str_Place represents the place in str_Campus. str_Campus is "North", "South", "East" or "Zhuhai". str_Place is a string which has less than one hundred lowercase characters from "a-z". You can assume that there is at most one road directly between any two places.
Output
The output of the program should consist of C lines, one line for each test case. For each test case, the output is a single line containing one integer. If there is a path between S and T, output the length of the shortest path between them. Otherwise just output "-1" (without quotation mark). No redundant spaces are needed.
Sample Input
12South.xiaolitang South.xiongdelong 2South.xiongdelong Zhuhai.liyuan 100South.xiongdelong South.xiaolitang
Sample Output
2
Problem Source
ZSUACM Team Member
题目是一个有权无向图求最短路径的问题,可以使用Dijkstra算法。由于这一算法求得是起始点到图中每一点的最短距离,且求的顺序按的是最短距离的升序,我们可以在求出至目的地点的最短距离后直接跳出即可。
关于这一算法的具体解释的文章:http://blog.csdn.net/tsinting/article/details/60575882
这题的输入比较坑,题目最后给出的起点和终点未必是图中的点,而Dijkstra算法要求输入的起点终点必须要在图中,所以要先行对起点终点进行判断。判断标准是:
1、只要起点终点相同,那么无论是否在图中,都输出0
2、如果起点终点不同,那么只要有任何一个不再图中,都输出-1
3、起终点不同且都在图中则调用Dijkstra算法,要求这一算法能在两点有路径是输出最短路径,无路径时输出-1
// Problem#: 1031
// Submission#: 5053036
// The source code is licensed under Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License
// URI: http://creativecommons.org/licenses/by-nc-sa/3.0/
// All Copyright reserved by Informatic Lab of Sun Yat-sen University
#include<iostream>
#include<vector>
#include<string>
#include<iterator>
#include<algorithm>
using namespace std;
const int maxDis=32760;//最大距离,当两点之间无道路时距离即为此值,代表不连通
const int maxNum=200;//最大的地点数量
int weight[maxNum][maxNum];//权重矩阵
vector<string> place;//将每个地点放入容器,地点在容器中的下标即是地点的序号
int dis[maxNum];//每个地点距离起点当前距离的数组
int C,N,placeNum;//C为case数,N为道路数量,placenum为地点数量
void readData()
{
for(int i=0;i<maxNum;++i)//由于不连通的点之间的距离为maxDis,所以不妨将所有点之间的距离先赋值为maxDis
{
for(int j=0;j<maxNum;++j)
weight[i][j]=maxDis;
}
string s1,s2;
int distance;
int pos1,pos2;
place.clear();
for(int i=0;i<N;++i)
{
cin>>s1>>s2>>distance;
if(find(place.begin(),place.end(),s1)==place.end()) place.push_back(s1);//若s1这一地点未出现过,则加入容器
if(find(place.begin(),place.end(),s2)==place.end()) place.push_back(s2);//s2也一样
pos1=find(place.begin(),place.end(),s1)-place.begin();//获取s1在容器中下标
pos2=find(place.begin(),place.end(),s2)-place.begin();//获取s2在容器中下标
weight[pos1][pos2]=weight[pos2][pos1]=distance;//对权重矩阵的相应位置赋值
}
placeNum=place.size();
}
int Dijkstra(int start,int end)
{
bool findShortest[maxNum];//这一数组是为了确定各个地点是否找到了最短路径,是则设为true
for(int i=0;i<placeNum;++i)
{
dis[i]=weight[start][i];//初始每个点到start点的距离即为权重矩阵中的数,即直接距离
findShortest[i]=false;//开始寻找之前全部置为false
}
dis[start]=0;//start到自己本身的最短距离为0
findShortest[start]=true;
for(int i=1;i<placeNum;++i)
{
int mindis=maxDis+1;
int u=start;
for(int j=0;j<placeNum;++j)//这一循环找出当前到起点的最短直接距离以及对应的点,此时到这一点的最短距离即为这一距离
{
if(!findShortest[j]&&dis[j]<mindis)
{
u=j;
mindis=dis[j];
}
}
findShortest[u]=true;
if(u==end&&dis[end]!=maxDis) return mindis;//若这一点为终点且最短距离不为maxDis则有最短路径,直接返回最短路径
else if(u==end&&dis[end]==maxDis) return -1;//找到了终点但最短路径为maxDis,说明无路径,所以返回-1
for(int j=0;j<placeNum;++j)//若u点不是目的地点,则以u点为中间点更新每个点到起点的距离,然后再进行循环
{
if(!findShortest[j]&&weight[u][j]<maxDis)
{
if(dis[u]+weight[u][j]<dis[j])
{
dis[j]=dis[u]+weight[u][j];
}
}
}
}
}
int main()
{
cin>>C;
for(int i=0;i<C;++i)
{
cin>>N;
readData();
string start,end;
cin>>start>>end;
if(start==end) cout<<0<<endl;//根据总结出来的规律进行输出
else
{
int Start=find(place.begin(),place.end(),start)-place.begin();
int End=find(place.begin(),place.end(),end)-place.begin();
if(Start==placeNum||End==placeNum) cout<<-1<<endl;
else cout<<Dijkstra(Start,End)<<endl;
}
}
return 0;
}