Shortest Path [3] pta

题目在最后,先讲思路,第一段代码即答案:

插个图方便理解:

建立在Dijkstra算法的基础上每次收集并确定一个v时,在for循环遍历v的每隔邻接点时,两个if判断
第一个if--如果满足dist[i]==dist[v]+Graph->G[v][i],则说明从v到i距离对于当前S到i的最短路,
由于count[v]里存放了S到v最短路的数量,所以count[i]+=count[v],即加上了S通过v到达i的路径数量;比如题目图里以v=7,i=2; 
第二个if--如果满足Graph->G[v][i]<INFINITY&&!collected[i]&&dist[i]>dist[v]+Graph->G[v][i]这三个条件,则说明S通过v到i比dist[i]更短,所以更新dist[i],同时count[i]=count[v],因为当前通过v到i的路就等于count[v],比如题目图里以v=7,i=s;

答案代码如下:

void ShortestDist( MGraph Graph, int dist[], int count[], Vertex S ){
	int v,i,min,j;
	static int collected[9999];
	collected[S]=1;//这句非常重要,进入循环前就要收录S,不加会出问题,因为Graph->G[S][S]=INFINITY 
	for(i=0;i<Graph->Nv;i++){//初始化最短距离和路径数 
		count[i]=0; 
		dist[i]=Graph->G[S][i];
		if(dist[i]<INFINITY) count[i]=1; 
	}
	dist[S]=0;
	while(1){
		v=-1;
		min=INFINITY;
		for(i=0;i<Graph->Nv;i++){//找出未收录且dist最小的点 
			if(!collected[i]&&dist[i]<min){//第二个判断条件可以直接屏蔽掉dist是INFINITY的点 
				v=i;
				min=dist[v];
			}
		}
		if(v==-1) break;//不存在这样的点 
		collected[v]=1;
		for(i=0;i<Graph->Nv;i++){
			if(dist[i]==dist[v]+Graph->G[v][i]){//对应解释里的第一个if 
				count[i]+=count[v];
			}
			if(Graph->G[v][i]<INFINITY&&!collected[i]){//对应解释里的第二个if 
				if(dist[i]>dist[v]+Graph->G[v][i]){
					dist[i]=dist[v]+Graph->G[v][i];
					count[i]=count[v];//非常重要,3-0-4-7-5,3-1-7-5,3-0-7-5 
				}
			}
		}
	}
	count[S]=1;
	for(i=0;i<Graph->Nv;i++){
		if(dist[i]==INFINITY) dist[i]=-1;
	}
	return;
}

题目:

Write a program to not only find the weighted shortest distances, but also count the number of different minimum paths from any vertex to a given source vertex in a digraph. It is guaranteed that all the weights are positive.

Format of functions:

 

void ShortestDist( MGraph Graph, int dist[], int count[], Vertex S );

where MGraph is defined as the following:

 

typedef struct GNode *PtrToGNode; struct GNode{ int Nv; int Ne; WeightType G[MaxVertexNum][MaxVertexNum]; }; typedef PtrToGNode MGraph;

The shortest distance from V to the source S is supposed to be stored in dist[V]. If V cannot be reached from S, store -1 instead. The number of different minimum paths from V to the source S is supposed to be stored in count[V] and count[S]=1.

Sample program of judge:

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

typedef enum {false, true} bool;
#define INFINITY 1000000
#define MaxVertexNum 10  /* maximum number of vertices */
typedef int Vertex;      /* vertices are numbered from 0 to MaxVertexNum-1 */
typedef int WeightType;

typedef struct GNode *PtrToGNode;
struct GNode{
    int Nv;
    int Ne;
    WeightType G[MaxVertexNum][MaxVertexNum];
};
typedef PtrToGNode MGraph;

MGraph ReadG(); /* details omitted */

void ShortestDist( MGraph Graph, int dist[], int count[], Vertex S );

int main()
{
    int dist[MaxVertexNum], count[MaxVertexNum];
    Vertex S, V;
    MGraph G = ReadG();

    scanf("%d", &S);
    ShortestDist( G, dist, count, S );

    for ( V=0; V<G->Nv; V++ )
        printf("%d ", dist[V]);
    printf("\n");
    for ( V=0; V<G->Nv; V++ )
        printf("%d ", count[V]);
    printf("\n");

    return 0;
}

/* Your function will be put here */

Sample Input (for the graph shown in the figure):

8 11
0 4 5
0 7 10
1 7 30
3 0 40
3 1 20
3 2 100
3 7 70
4 7 5
6 2 1
7 5 3
7 2 50
3

Sample Output:

40 20 100 0 45 53 -1 50 
1 1 4 1 1 3 0 3 

最后是一点小私心,我的草稿,即调试过程:

void ShortestDist( MGraph Graph, int dist[], int count[], Vertex S ){
	int v,i,min,j;
	static int collected[9999];
	collected[S]=1;//这句非常重要,进入循环前就要收录S,不加会出问题 
	//因为Graph->G[S][S]=INFINITY 
	//printf("%d\n",Graph->G[S][S]);
	for(i=0;i<Graph->Nv;i++){//初始化最短距离和路径数 
		count[i]=0; 
		dist[i]=Graph->G[S][i];
		if(dist[i]<INFINITY) count[i]=1; 
	}
	dist[S]=0;
	while(1){
		v=-1;
		min=INFINITY;
		for(i=0;i<Graph->Nv;i++){//找出未收录且dist最小的点 
			if(!collected[i]&&dist[i]<min){//第二个判断条件可以直接屏蔽掉dist是INFINITY的点 
				v=i;
				min=dist[v];
			}
		}
		if(v==-1) break;//不存在这样的点 
		collected[v]=1;
		for(i=0;i<Graph->Nv;i++){
			if(dist[i]==dist[v]+Graph->G[v][i]){
				count[i]+=count[v];
//				printf("%d %d\n",i,v);
			//	for(j=0;j<Graph->Nv;j++){
			//		if(Graph->G[i][j]<INFINITY&&Graph->G[i][j]+dist[i]==dist[j]){
			//			count[j]++;//3-0-4-7-2和3-0-4-7-2这种情况 
			//		}
			//	} 
			}
			if(Graph->G[v][i]<INFINITY&&!collected[i]){
				if(dist[i]>dist[v]+Graph->G[v][i]){
					dist[i]=dist[v]+Graph->G[v][i];
					count[i]=count[v];//非常重要,3-0-4-7-5,3-1-7-5,3-0-7-5 
				}
			}
		}
	}
	count[S]=1;
	for(i=0;i<Graph->Nv;i++){
		if(dist[i]==INFINITY) dist[i]=-1;
	}
	return;

  • 13
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值