1003. Emergency


这道题一开始就卡在了题目没看清这个问题上。题目是最短路径的变形,但是输出要求的最短路径的条数和路径上结点值的最大和。

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

#define MaxVertexNum 500
#define INFINITY 65535                  /* 二进制的2^16,即int类型最大储存值 */

typedef int ElementType;
typedef int WeightType;
typedef int Vertex;


/* 图结点 */
struct GNode{
    int Nv, Ne;
    WeightType G[MaxVertexNum][MaxVertexNum];
    ElementType Data[MaxVertexNum];
};
typedef struct GNode *PtrToGNode;
typedef PtrToGNode MGraph;


MGraph CreateGraph(int VertexNum);
MGraph BuildGraph(int M, int N);
void Dijkstra_X(MGraph Graph, int path[], int dist[], Vertex S, Vertex E);
Vertex FindMindist(MGraph Graph, int dist[], int collected[]);


int main()
{
    //freopen("C:\\Users\\ChanWunsam\\Desktop\\pat\\pat_in.txt","r",stdin);
    //freopen("C:\\Users\\ChanWunsam\\Desktop\\pat\\pat_out.txt","w",stdout);

    int M, N, C1, C2;
    int dist[MaxVertexNum], path[MaxVertexNum], Sum;
    MGraph Graph;
    Vertex W;

    scanf("%d %d %d %d", &M, &N, &C1, &C2);
    Graph=BuildGraph(M, N);
    if(C1==C2)                                  /* 如果起始地和目的地相同 */
    {
        printf("%d %d", 1, Graph->Data[C1]);
    }
    else
        Dijkstra_X(Graph, dist, path, C1, C2);

    return 0;
}


MGraph CreateGraph(int VertexNum)
{
    Vertex V, W;
    MGraph Graph;

    Graph=(MGraph)malloc(sizeof(struct GNode));
    Graph->Nv=VertexNum;
    Graph->Ne=0;
    for(V=0; V<VertexNum; V++)
    {
        Graph->Data[V]=-1;
        for(W=0; W<VertexNum; W++)
        {
            Graph->G[V][W]=INFINITY;
        }
    }

    return Graph;
}

MGraph BuildGraph(int M, int N)
{
    int data, i;
    Vertex V, W;
    WeightType Weight;
    MGraph Graph;

    Graph=CreateGraph(M);
    Graph->Ne=N;

    for(V=0; V<Graph->Nv; V++)
    {
        scanf("%d", &data);
        Graph->Data[V]=data;
    }
    for(i=0; i<Graph->Ne; i++)
    {
        scanf("%d %d %d", &V, &W, &Weight);
        /* 插入边 */
        Graph->G[V][W]=Weight;
        Graph->G[W][V]=Weight;
    }

    return Graph;
}

void Dijkstra_X(MGraph Graph, int path[], int dist[], Vertex S, Vertex E)   /* 单源最短路径算法变形 */
{
    /* path记录每个点的最短路径条数,dist记录每个点的最短路径长度,Sum记录每个点的最短路径上的最大救援队数量 */
    int collected[MaxVertexNum], Sum[MaxVertexNum];
    Vertex V, W;

    /* 初始化:此处默认邻接矩阵中不存在的边用INFINITY表示 */
    dist[S] = 0;
    collected[S] = true;
    Sum[S]=Graph->Data[S];

    for ( V=0; V<Graph->Nv; V++ )
    {
        if(V==S)
            V++;

        dist[V] = Graph->G[S][V];
        if ( dist[V]<INFINITY )
        {
            Sum[V]=Sum[S]+Graph->Data[V];
            path[V] = 1;
        }
        else                                    /* 如果没有路径,赋值-1,方便检查 */
        {
            Sum[V]=-1;
            path[V] = -1;
        }
        collected[V] = false;
    }


    while (1) {
        /* V = 未被收录顶点中dist最小者 */
        V = FindMindist( Graph, dist, collected );
        if ( V==-1 ) /* 若这样的V不存在 */
            break;      /* 算法结束 */
        collected[V] = true;  /* 收录V */
        for( W=0; W<Graph->Nv; W++ ) /* 对图中的每个顶点W */
            /* 若W是V的邻接点并且未被收录 */
            if ( collected[W]==false && Graph->G[V][W]<INFINITY ) {
                /* 若收录V使得dist[W]变小 */
                if ( dist[V]+Graph->G[V][W] < dist[W] ) {
                    dist[W] = dist[V]+Graph->G[V][W];            /* 更新dist[W] */
                    path[W] = path[V];
                    Sum[W]=Sum[V]+Graph->Data[W];
                }
                else if(dist[V]+Graph->G[V][W] == dist[W]){
                    path[W]+=path[V];
                    if(Sum[V]+Graph->Data[W] > Sum[W])
                        Sum[W]=Sum[V]+Graph->Data[W];
                }
            }
    } /* while结束*/

    printf("%d %d", path[E], Sum[E]);
}

Vertex FindMindist(MGraph Graph, int dist[], int collected[])
{
    Vertex V, MinV;
    int MinDist;

    MinDist=INFINITY;
    for(V=0; V<Graph->Nv; V++)
    {
        if(!collected[V] && dist[V]<MinDist)
        {
            MinDist=dist[V];
            MinV=V;
        }
    }

    if(MinDist<INFINITY)
        return MinV;
    else
        return -1;
}

实在做太久了,这周的任务铁定完不成。

最后是卡在了第二个测试点,这个测试点是起始点和目的点相同,输出会比较特殊。

需要注意的是path和Sum的更新方法,不是递加而是加上前面结点的值。

我的代码可能看起来比较方便,但是时间复杂度和空间复杂度就没那么好了,就这样吧。

猜你喜欢

转载自www.cnblogs.com/ChanWunsam/p/10018205.html