HDOJ-2066-一个人的旅行

Problem Description
虽然草儿是个路痴(就是在杭电待了一年多,居然还会在校园里迷路的人,汗~),但是草儿仍然很喜欢旅行,因为在旅途中 会遇见很多人(白马王子,^0^),很多事,还能丰富自己的阅历,还可以看美丽的风景……草儿想去很多地方,她想要去东京铁塔看夜景,去威尼斯看电影,去阳明山上看海芋,去纽约纯粹看雪景,去巴黎喝咖啡写信,去北京探望孟姜女……眼看寒假就快到了,这么一大段时间,可不能浪费啊,一定要给自己好好的放个假,可是也不能荒废了训练啊,所以草儿决定在要在最短的时间去一个自己想去的地方!因为草儿的家在一个小镇上,没有火车经过,所以她只能去邻近的城市坐火车(好可怜啊~)。

Input
输入数据有多组,每组的第一行是三个整数T,S和D,表示有T条路,和草儿家相邻的城市的有S个,草儿想去的地方有D个;
接着有T行,每行有三个整数a,b,time,表示a,b城市之间的车程是time小时;(1=<(a,b)<=1000;a,b 之间可能有多条路)
接着的第T+1行有S个数,表示和草儿家相连的城市;
接着的第T+2行有D个数,表示草儿想去地方。

Output
输出草儿能去某个喜欢的城市的最短时间。

Sample Input
6 2 3
1 3 5
1 4 7
2 8 12
3 8 4
4 9 12
9 10 2
1 2
8 9 10

Sample Output
9

题比较直观,即单源求最短路,可以用spfa算法,也可以用floyd算法。

sofa:

#include<stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAXSIZE 1000
#define INF 0x3f3f3f3f //表示无穷大
//#define MAX(a, b) a > b ? a : b
//#define MIN(a, b) a < b ? a : b
typedef void Status;
typedef int QElemType;

struct node
{
    int from;
    int to;
    int time;
    int next;
} edge[10 * MAXSIZE];

int head[MAXSIZE];
int vis[MAXSIZE];
int map[MAXSIZE];
int b[MAXSIZE];
int e[MAXSIZE];
int edgeNum, T;

//循环队列顺序存储结构
typedef struct
{
    QElemType data[MAXSIZE];
    int front;  //头指针
    int reat;   //尾指针,若队列不空,指向队列尾元素的下一个位置
} SqQueue;

//初始化一个空队列
Status InitQueue(SqQueue *Q)
{
    Q->front = 0;
    Q->reat = 0;
    return ;
}

//返回Q的元素个数,也就是队列当前长度
int QueueLength(SqQueue Q)
{
    return (Q.reat - Q.front + MAXSIZE) % MAXSIZE;
}

//若队列未满,则插入元素e为Q新队尾元素
Status EnQueue(SqQueue *Q, QElemType e)
{
    if ((Q->reat + 1) % MAXSIZE == Q->front)
    {
        return ;
    }

    Q->data[Q->reat] = e;
    Q->reat = (Q->reat + 1) % MAXSIZE;
    return ;
}

//若队列不空,则删除Q中队头元素
Status DeQueue(SqQueue *Q)
{
    if (Q->front == Q->reat)
    {
        return ;
    }
    Q->front = (Q->front + 1) % MAXSIZE;
    return ;
}

void init()
{
    //初始化为-1
    memset(map, -1, sizeof(map));

    edgeNum = 0;
    return ;
}

void add(int a, int b, int time)
{
    struct node E = {a, b, time, head[a]};
    edge[edgeNum] = E;
    head[a] = edgeNum++;
    return ;
}

//佛洛依德算法,最短路
void spfa(int neiCity)
{
    SqQueue Q;
    InitQueue(&Q);
    memset(vis, 0, sizeof(vis));
    memset(map, 0x3f, sizeof(map));

    vis[neiCity] = 1;
    map[neiCity] = 0;

    EnQueue(&Q, neiCity);

    while (QueueLength(Q))
    {
        int u = Q.front, i;
        DeQueue(&Q);
        vis[u] = 0;
        for (i = head[u]; i != -1; i = edge[i].next)
        {
            int v = edge[i].to;
            if (map[v] > map[u] + edge[i].time)
            {
                map[v] = map[u] + edge[i].time;
                if (!vis[v])
                {
                    vis[v] = 1;
                    EnQueue(&Q, v);
                }
            }
        }
    }
    return ;
}

int main()
{
    int T, S, D;
    int a, b, time;
    int neiCity[MAXSIZE], goCity[MAXSIZE];
    int i, j, min;
    while (~scanf("%d %d %d", &T, &S, &D))
    {
        init();

        while (T--)
        {
            scanf("%d %d %d", &a, &b, &time);

            add(a, b, time);
            add(b, a, time);    //双向图
        }

        for (i = 0; i < S; i++)
        {
            scanf("%d", neiCity + i);
        }

        for (i = 0; i < D; i++)
        {
            scanf("%d", goCity + i);
        }

        min = INF;

        for (i = 0; i < S; i++)
        {
            spfa(neiCity[i]);
            for (j = 0; j < D; j++)
            {
                if (min > map[goCity[j]])
                {
                    min = map[goCity[j]];
                }
            }
        }
        printf("%d\n", min);
    }
    return 0;
}

floyd:

#include<stdio.h>
#include <string.h>
#define MAXSIZE 1000
#define INF 0x3f3f3f3f //表示无穷大
#define MAX(a, b) a > b ? a : b
#define MIN(a, b) a < b ? a : b

int map[MAXSIZE][MAXSIZE];

void init()
{
    //初始化为无穷大
    memset(map, 0x3f, sizeof(map));

    for (int i = 1; i < MAXSIZE; i++)
    {
        map[i][i] = 0;
    }

    return ;
}

//佛洛依德算法,最短路
void floyd(int n)
{
    int i, j, k;
    for (k = 1; k <= n; k++)
    {
        for (i = 1; i <= n; i++)
        {
            if (map[i][k] != INF)
            {
                for (j = 1; j <= n; j++)
                {
                    map[i][j] = MIN(map[i][j], map[i][k] + map[k][j]);
                }
            }
        }
    }
    return ;
}

int main()
{
    int T, S, D;
    int a, b, time;
    int neiCity[MAXSIZE], goCity[MAXSIZE];
    int i, j, n, min;
    while (~scanf("%d %d %d", &T, &S, &D))
    {
        init();
        n = -1;

        while (T--)
        {
            scanf("%d %d %d", &a, &b, &time);

            if (map[a][b] > time)
            {
                map[a][b] = map[b][a] = time;
            }

            n = MAX(MAX(n, a), b);
        }

        for (i = 0; i < S; i++)
        {
            scanf("%d", neiCity + i);
        }

        for (i = 0; i < D; i++)
        {
            scanf("%d", goCity + i);
        }

        floyd(n);

        min = INF;

        for (i = 0; i < S; i++)
        {
            for (j = 0; j < D; j++)
            {
                min = MIN(min, map[i][goCity[j]]);
            }
        }

        printf("%d\n", min);
    }
    return 0;
}

如果用C写的话,建议用第二种,毕竟第一种需要用到队列,而队列需要自己去实现。好处是,自己写的队列可以进行优化,将不必要的功能删去。

你可能感兴趣的:(最短路,SPFA,floyd)