题目在最后,先讲思路,第一段代码即答案:
插个图方便理解:
建立在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;