1. 程式人生 > >1003. Emergency

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的更新方法,不是遞加而是加上前面結點的值。

我的程式碼可能看起來比較方便,但是時間複雜度和空間複雜度就沒那麼好了,就這樣吧。