1:我爱北大

总时间限制: 
1000ms 
内存限制: 
65535kB
描述

“红楼飞雪,一时英杰……”耳边传来了那熟悉的歌声。而这,只怕是我最后一次听到这个声音了。

想当年,我们曾经怀着豪情壮志,许下心愿,走过静园,走过一体,走过未名湖畔的每个角落。

想当年,我们也曾慷慨高歌,瞻仰民主与科学,瞻仰博雅塔顶,那百年之前的遗韵。

没错,我爱北大,我爱这个校园。

然而,从当我们穿上学位服的那一刻起,这个校园,就再也不属于我。它只属于往事,属于我的回忆。

没错,这,是我在北大的最后一日。此时,此景,此生,此世,将刻骨难忘。

再也没有了图书馆自习的各种纷纭,再也没有了运动场上的挥汗如雨,有的,只是心中永远的不舍,与牵挂。

夜,已深。人,却不愿离去。天边有一颗流星划过,是那般静,宁谧。

忍不住不回头,我的眼边,有泪光,划过。

这时候,突然有一位路人甲从你身旁出现,问你:从XX到XX怎么走?

索性,就让我再爱你一次。因为,北大永远在你心中。北大的地图,永远在你的心中。

轻手挥扬,不带走一分云彩。

输入
输入分为三个部分。
第一个部分有P+1行,第一行为一个整数P,之后的P行表示北大的地点。
第二个部分有Q+1行,第一行为一个整数Q,之后的Q行每行分别为两个字符串与一个整数,表示这两点有直线的道路,并显示二者之间的矩离(单位为米)。
第三个部分有R+1行,第一行为一个整数R,之后的R行每行为两个字符串,表示需要求的路线。
p<30,Q<50,R<20
输出
输出有R行,分别表示每个路线最短的走法。其中两个点之间,用->(矩离)->相隔
样例输入
6
XueYiShiTang
CanYinZhongXin
XueWuShiTang
XueYiXiaoBaiFang
BaiNianJiangTang
GongHangQuKuanJi
6
XueYiShiTang CanYinZhongXin 80
XueWuShiTang CanYinZhongXin 40
XueYiShiTang XueYiXiaoBaiFang 35
XueYiXiaoBaiFang XueWuShiTang 85
CanYinZhongXin GongHangQuKuanJi 60
GongHangQuKuanJi BaiNianJiangTang 35
1
XueYiXiaoBaiFang BaiNianJiangTang
样例输出
XueYiXiaoBaiFang->(35)->XueYiShiTang->(80)->CanYinZhongXin->(60)->GongHangQuKuanJi->(35)->BaiNianJiangTang
提示

很O疼的一道题。。。说出不少伤感事啊。两个最短路的算法都是可以用的,可以视情况选择你习惯的那个算法。



迪杰斯特算法。单源最短路。曾近想又用堆去做优先队列。。但是在鱼c教程看到一个循环就可以找到。

所以贪方便抄下来了。算法复杂度感觉还是 O(n^2)

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<assert.h>
#include<ctype.h>
#include<stdlib.h>
#define max 0xffffff
using namespace std;
char ads[32][100];
int vis[32];
int G[32][32];
int D[32];///用来存放起点到每个节点的长度
int pre[32];///每个节点的前驱
int p;
void init(  )
{
    for(int i = 0; i < p; i++)
        for(int j=0; j < p; j++)
            G[i][j] = max;
}
void print(int e)//输出。
{
    if(e==pre[e]){printf("%s",ads[e]);return ;}
   else print(pre[e]);
    printf("->(%d)->%s",G[pre[e]][e],ads[e]);
}
void dijkstra(int start,int end)
{
    for(int i = 0; i < p; ++i)
    {
        vis[i] = 0;
        D[i] = G[start][i];
        pre[i] = start;///前驱全部初始化为起点。这里刚刚写的时候没有  得不到正确答案。
       // printf("%d      %d\n",D[i],i);
    }
    //printf("\n__________________\n");
    vis[start] = 1;
    pre[start] = start;
    D[start] = 0;
    bool found = false;
    int k;
    for(int i = 0; i < p; i++)
    {
        int min = max;
        int j;
        for(j=0; j < p; j++) ///找到权最小的路径
        {
            if(!vis[j] && D[j]<min)
            {   k = j;
                min = D[j];
                //printf("%d$$$\n",min);
            }
        }
        vis[k] = 1;

        for(j=0; j<p; j++) //修改曾有的路径
        {
            if(!vis[j]&&(min+G[k][j])<D[j])
            {
                D[j] = min + G[k][j];
                pre[j] = k;
                if(j == end)found = true;
            }
        }
        for(j=0;j<p;j++)
        /*printf("%4d",D[j]);
        printf("\n");*/
        if(found)break;
    }
    print(end);
}


int main()
{
   // freopen("in.txt","r",stdin);
  /// freopen("out.txt","w",stdout);
    scanf("%d",&p);

        int i,j;//计数器
        for(i = 0; i < p; i++)
        {
            scanf("%s",ads[i]);
        }
        init();
        int Q;
        scanf("%d",&Q);
        for(i=0; i<Q; i++)
        {
            int a1 = -1, b1= -1;
            char a[100],b[100];
            int W;
            scanf("%s%s%d",a,b,&W);
            for(j=0; j < p&&(a1==-1||b1==-1); j++)
            {
                if(!strcmp(a,ads[j]))a1 = j;
                if(!strcmp(b,ads[j]))b1 = j;
            }
            G[a1][b1] = W;
            G[b1][a1] = W;
            //printf("%s_____%s\n\n%d........%d\n\nlen = %d}}}\\\n",a,b,a1,b1,G[a1][b1]);
        }
       // printf("()()()()(\n");
        /*for(int i = 0; i < p; i++)
        {
            printf("ads%s=%d\n",ads[i],i);
        }*/
        int R;
        scanf("%d",&R);
        for(i=0; i<R; i++)
        {
            int a1 = -1, b1= -1;
            char a[100],b[100];
            int W;
            scanf("%s%s",a,b);
            for(j=0; j < p&&(a1==-1||b1==-1); j++)
            {
                if(!strcmp(a,ads[j]))a1 = j;
                else  if(!strcmp(b,ads[j]))b1 = j;
            }
            dijkstra(a1,b1);
            printf("\n");
        }


    return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值