No1031.Campus

一、题目描述

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.

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

1
2
South.xiaolitang South.xiongdelong 2
South.xiongdelong Zhuhai.liyuan 100
South.xiongdelong South.xiaolitang

Sample Output

2

二、方法一

1、算法简介

(1)因为不存在负边,则可以使用Dijkstra算法求单源最短路径。Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径。主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。时间复杂度为O((|V|+|E|)log|V|)。

(2)算法思想:设G=(V,E)是一个带权有向图,把图中顶点集合V分成两组,第一组为已求出最短路径的顶点集合(用S表示,初始时S中只有一个源点,以后每求得一条最短路径 , 就将加入到集合S中,直到全部顶点都加入到S中,算法就结束了),第二组为其余未确定最短路径的顶点集合(用U表示),按最短路径长度的递增次序依次把第二组的顶点加入S中。在加入的过程中,总保持从源点v到S中各顶点的最短路径长度不大于从源点v到U中任何顶点的最短路径长度。此外,每个顶点对应一个距离,S中的顶点的距离就是从v到此顶点的最短路径长度,U中的顶点的距离,是从v到此顶点只包括S中的顶点为中间顶点的当前最短路径长度。

(3)算法步骤:

a.初始时,S只包含源点,即S={v},v的距离为0。U包含除v外的其他顶点,即:U={其余顶点},若v与U中顶点u有边,则<u,v>正常有权值,若u不是v的出边邻接点,则<u,v>权值为∞。

b.从U中选取一个距离v最小的顶点k,把k,加入S中(该选定的距离就是v到k的最短路径长度)。

c.以k为新考虑的中间点,修改U中各顶点的距离;若从源点v到顶点u的距离(经过顶点k)比原来距离(不经过顶点k)短,则修改顶点u的距离值,修改后的距离值的顶点k的距离加上边上的权。

d.重复步骤b和c直到所有顶点都包含在S中。

2、代码实现

#include<iostream>
#include<string>
#include<cstring>
#include<map>

using namespace std;

#define MAX 200 //定义一个最大值
#define INF 1000000  //定义一个无穷大值

int buff[MAX][MAX]; //记录原始每条边的长度
int length[MAX];  //记录从起点b到各个顶点的最短路径
bool visited[MAX];  //记录所有访问过的点

int dijkstra(int b,int e,int count){
    for(int i=0;i<sizeof(visited);i++) //对于每一组新的数据,将记录访问过的节点初始化为全false
        visited[i]=false;
    for(int i=0;i<count;i++) //将从顶点到各个顶点的距离初始化为无穷大
        length[i]=INF;
    length[b]=0; //将起始点b到自己的距离初始化为0
    for(int i=0;i<count;i++){  //循环count次,遍历每一个节点
        int min =INF; //min用于记录相对于起点的最短的距离
        int v= b;  //记录最短距离对应的节点
        for(int j=0;j<count;j++){ //遍历每一个节点,寻找距离顶点最近的且未访问的点
            if(!visited[j]&&length[j]<min){ //如果这个节点没有被访问过并且到起点的距离比最短的还短
                min = length[j]; //更新最短距离
                v=j;  //更新该最短距离对应的节点
            }
        }
        visited[v]=true;  //v是目前距离起点最近的点,则将它拉入访问过的集合中
        for(int j=0;j<count;j++){   //将节点拉入访问过的节点之后,遍历每个节点
            if(!visited[j]&&length[v]+buff[v][j]<length[j]){  //如果从起点到新加入的v点再到j点的距离小于从起点直接到j点的距离
                length[j]=length[v]+buff[v][j]; //则将从起点到j点的距离更新为更短的长度
            }
        }
    }
    if(visited[e]) return length[e];
    else return -1;
}

int main(){
    int c;
    cin>>c;
    while(c--){
        int n,dis;
        string b,e;
        map<string,int> sysu; //用于将一个字符串映射到一个数字
        int count= 0;
        cin>>n;
        for(int i=0;i<MAX;i++){
            for(int j=0;j<MAX;j++){
                buff[i][j]=(i==j?0:INF); //初始化buff数组,一个点到自己的距离是0,到其他点的距离是无穷远
            }
        }
        for(int i=0;i<n;i++){
            cin>>b>>e>>dis;
            if(!sysu.count(b)) sysu[b]=count++; //如果起始点是新加入的点,则给它赋一个新值
            if(!sysu.count(e)) sysu[e]=count++; //如果终结点是新加入的点,则给它赋一个新值
            buff[sysu[b]][sysu[e]]=buff[sysu[e]][sysu[b]]=dis; //记录b到e的边的长度
        }
        cin>>b>>e;
        if(b==e) cout<<0<<endl; //如果b和e是同一个点,则返回0
        else if(!sysu.count(b)||!sysu.count(e)) cout<<-1<<endl; //如果b和e是新的点,则返回-1
        else cout<<dijkstra(sysu[b],sysu[e],count)<<endl; //传入b、e和节点个数,调用dijkstra函数
    }
    return 0;
}

三、方法二

1、算法简介

      Floyd-Warshall算法(Floyd-Warshall algorithm)是解决任意两点间的最短路径的一种算法,可以正确处理有向图或负权的最短路径问题,同时也被用于计算有向图的传递闭包。Floyd-Warshall算法的时间复杂度为O(N3),空间复杂度为O(N2)。

      Floyd算法是一个经典的动态规划算法。用通俗的语言来描述的话,首先我们的目标是寻找从点i到点j的最短路径。从动态规划的角度看问题,我们需要为这个目标重新做一个诠释(这个诠释正是动态规划最富创造力的精华所在)

      从任意节点i到任意节点j的最短路径不外乎2种可能,1是直接从i到j,2是从i经过若干个节点k到j。所以,我们假设Dis(i,j)为节点u到节点v的最短路径的距离,对于每一个节点k,我们检查Dis(i,k) + Dis(k,j) < Dis(i,j)是否成立,如果成立,证明从i到k再到j的路径比i直接到j的路径短,我们便设置Dis(i,j) = Dis(i,k) + Dis(k,j),这样一来,当我们遍历完所有节点k,Dis(i,j)中记录的便是i到j的最短路径的距离。

2、代码实现

#include<iostream>
#include<string>
#include<cstring>
#include<map>

using namespace std;

#define MAX 200 //定义一个最大值
#define INF 1000000  //定义一个无穷大值

int buff[MAX][MAX]; //记录原始每条边的长度

int main(){
    int c;
    cin>>c;
    while(c--){
        int n,dis;
        string b,e;
        map<string,int> sysu; //用于将一个字符串映射到一个数字
        int count= 0;
        cin>>n;
        for(int i=0;i<MAX;i++){
            for(int j=0;j<MAX;j++){
                buff[i][j]=(i==j?0:INF); //初始化buff数组,一个点到自己的距离是0,到其他点的距离是无穷远
            }
        }
        for(int i=0;i<n;i++){
            cin>>b>>e>>dis;
            if(!sysu.count(b)) sysu[b]=count++; //如果起始点是新加入的点,则给它赋一个新值
            if(!sysu.count(e)) sysu[e]=count++; //如果终结点是新加入的点,则给它赋一个新值
            buff[sysu[b]][sysu[e]]=buff[sysu[e]][sysu[b]]=dis; //记录b到e的边的长度
        }
        cin>>b>>e;
        if(b==e) cout<<0<<endl; //如果b和e是同一个点,则返回0
        else if(!sysu.count(b)||!sysu.count(e)) cout<<-1<<endl; //如果b和e是新的点,则返回-1
        else{
            for(int k=0;k<count;k++){
                for(int i=0;i<count;i++){
                    for(int j=0;j<count;j++){
                        if(buff[i][j]>buff[i][k]+buff[k][j])
                            buff[i][j]=buff[i][k]+buff[k][j];
                    }
                }
            }
            if(buff[sysu[b]][sysu[e]]==INF)cout<<-1<<endl;
            else cout<<buff[sysu[b]][sysu[e]]<<endl;
        }
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值