poj1847 - Tram (最短路径问题) (Dijkstra)

Tram
Time Limit: 1000MS Memory Limit: 30000K
Total Submissions: 10231 Accepted: 3739

Description

Tram network in Zagreb consists of a number of intersections and rails connecting some of them. In every intersection there is a switch pointing to the one of the rails going out of the intersection. When the tram enters the intersection it can leave only in the direction the switch is pointing. If the driver wants to go some other way, he/she has to manually change the switch.

When a driver has do drive from intersection A to the intersection B he/she tries to choose the route that will minimize the number of times he/she will have to change the switches manually.

Write a program that will calculate the minimal number of switch changes necessary to travel from intersection A to intersection B.

Input

The first line of the input contains integers N, A and B, separated by a single blank character, 2 <= N <= 100, 1 <= A, B <= N, N is the number of intersections in the network, and intersections are numbered from 1 to N.

Each of the following N lines contain a sequence of integers separated by a single blank character. First number in the i-th line, Ki (0 <= Ki <= N-1), represents the number of rails going out of the i-th intersection. Next Ki numbers represents the intersections directly connected to the i-th intersection.Switch in the i-th intersection is initially pointing in the direction of the first intersection listed.

Output

The first and only line of the output should contain the target minimal number. If there is no route from A to B the line should contain the integer "-1".

Sample Input

3 2 1
2 2 3
2 3 1
2 1 2

Sample Output

0

Source

 
 
     题意:
              地区之间的铁路交织形成铁路网。有轨电车在每个路口都能根据该路口铁路的转向,去到不同的路口。虽然每个路口都有多条分岔路,但是每个路口只会指向其中的一条。若想要去其他的分岔路,则需要通过路口上的相应开关重新设置其转向。先给定各路口每条分岔路可到达的下一个路口,以及该路口一开始指向哪个路口。问若需要从某一路口到达另一路口,至少需要设置几次开关才能去到。
     输入输出:         
               先给出N个点和A、B(起终点),接下来的N行分别为点i(1-N)的情况,第一个数表示与该点连通的个数,接下来给该行Ki个点,k1点所连为默认,通过不需要改转向,其余需要改一次转向,求改转向次数最少。
    思路: 先构造有向图,将不需要改转向的路线设为0,否则为1,求最短路径即可。
/******************************
*
*	acm: poj-1847
*
*	title: Tram
*
*	time :2014.8.26
*
*******************************/

/*
     输入输出:
           先给出N个点和A、B(起终点),接下来的N行分别为点i(1-N)的情况,
           第一个数表示与该点连通的个数,接下来给该行Ki个点,k1点所连为默认,
           通过不需要改转向,其余需要改一次转向,求改转向次数最少。
    思路:
           先构造有向图,将不需要改转向的路线设为0,否则为1,求最短路径即可。
*/

#include <stdio.h>
#include <stdlib.h>

#define OK 1
#define ERROR 0

#define TRUE 1
#define FALSE 0

#define INFINITY 65535

#define MAXVEX 101

typedef int EdgeType;


//构造邻接矩阵
typedef struct MGraph
{
    EdgeType arc[MAXVEX][MAXVEX];
    int numVertexes;
} MGraph;

//初始化图结构
void CreateMGraph(MGraph *G)
{
    int i, j;
    int n;        //点i的情况
    int a;

    for (i = 1; i <= G->numVertexes; i++)
    {
        for (j = i; j <= G->numVertexes; j++)
        {
            if (i == j)
            {
                G->arc[i][j] = 0;
            }
            else
            {
                G->arc[j][i] = G->arc[i][j] = INFINITY;
            }
        }
    }

    for (i = 1; i<= G->numVertexes; i++)
    {
        scanf("%d", &n);   //点i的可能情况

        for (j = 0; j < n; j++)
        {
            scanf("%d", &a);

            if (j == 0)
            {
                G->arc[i][a] = 0;
            }
            else
            {
                G->arc[i][a] = 1;
            }

        }
    }

/*  静态数据

    G->arc[1][2] = 0;
    G->arc[1][3] = 1;

    G->arc[2][3] = 0;
    G->arc[2][1] = 1;

    G->arc[3][1] = 0;
    G->arc[3][2] = 1;

*/
}

typedef int ShortPathTable[MAXVEX];

//Dijkstra 算法 D[v] 带权路径长度
int  ShortestPath_Dijkstra(MGraph G, int v0, int vw)
{
    int v, w, k, min;
    int final[MAXVEX];  //final[w]=1 表示求得顶点v0至vw的最短路径
    ShortPathTable D;

    for (v = 1; v <= G.numVertexes; v++)
    {
        final[v] = 0;           //全部顶点初始化为未知最短路径的状态
        D[v] = G.arc[v0][v];    //将与v0有连线的顶点加上权值
    }

    final[v0] = 1;

    //开始主循环,每次求得v0到某个v顶点的最短路径
    for (v = 1; v < G.numVertexes; v++)
    {
        min = INFINITY;

        for (w = 1; w <= G.numVertexes; w++)  //寻找离v0最近的顶点
        {
            if (!final[w] && D[w] < min)
            {
                k = w;
                min = D[w];   //w顶点离v0更近
            }
        }

        final[k] = 1;

        for (w = 1 ; w <= G.numVertexes; w++)  //修正当前最短距离
        {
            //如果经过v顶点的路径比现在这条路径的长度短的话
            if (!final[w] && (min + G.arc[k][w] < D[w]))
            {
                //说明找到了更短的路径,修改D[w]
                D[w] = min + G.arc[k][w];
            }
        }

        if (final[vw] == 1)
        {
            break;
        }
    }

    if (D[vw] == INFINITY)
    {
        D[vw] = -1;
    }

    return D[vw];

}


int main()
{
    int n;
    int a;
    int b;
    MGraph G;

    while (~scanf("%d", &G.numVertexes))
    {
        scanf("%d%d", &a, &b);
        CreateMGraph(&G);

        n = ShortestPath_Dijkstra(G, a, b);

        printf("%d\n", n);
    }

    return 0;
}

 
         
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值