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的更新方法,不是递加而是加上前面结点的值。

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

原文地址:https://www.cnblogs.com/ChanWunsam/p/10018205.html