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

typedef char VertexType[4];
typedef char InfoPtr;
typedef int VRType;
#define INFINITY 100000		//定义一个无限大的值
#define MaxSize 50	//最大顶点个数
typedef int PathMatrix[MaxSize][MaxSize][MaxSize];	//定义一个保存最短路径的二维数组
typedef int ShortPathLength[MaxSize][MaxSize];	//定义一个保存从顶点v0到顶点v的最短距离的数组
typedef enum{DG,DN,UG,UN}GraphKind;
typedef struct{
	VRType adj;		//对于无权图,用1表示相邻,0表示不相邻;对于带权图,存储权值
	InfoPtr *info;	//与弧或边的相关信息
}ArcNode,AdjMatrix[MaxSize][MaxSize];
//图的类型定义
typedef struct{
	VertexType vex[MaxSize];	//用于存储顶点
	AdjMatrix arc;		//邻接矩阵,存储边或弧的信息
	int vexnum,arcnum;	//顶点数和边(弧)的数目
	GraphKind kind;	//图的类型
}MGraph;
//加入一个存储网的行、列和权值的类型定义
typedef struct{
	int row;
	int col;
	int weight;
}GNode;
//採用邻接矩阵表示法创建有向网N
void CreateGraph(MGraph *N,GNode *value,int vnum,int arcnum,VertexType *ch){
	int i,j,k,w;
	char s[MaxSize];
	VertexType v1,v2;
	N->vexnum=vnum;
	N->arcnum=arcnum;
	for(i=0;i<vnum;i++)
		strcpy(N->vex[i],ch[i]);
	//初始化邻接矩阵
	for(i=0;i<N->vexnum;i++)	
		for(j=0;j<N->vexnum;j++){
			N->arc[i][j].adj=INFINITY;
			N->arc[i][j].info=NULL;	//弧的信息初始化为空
		}
		for(k=0;k<arcnum;k++){
			i=value[k].row;
			j=value[k].col;
			N->arc[i][j].adj=value[k].weight;
		}
		N->kind=DN;	//图的类型为有向网
}
//输出邻接矩阵存储表示的图N
void DisplayGraph(MGraph N){
	int i,j;
	printf("有向网具有%d个顶点%d条弧,顶点依次是: ",N.vexnum,N.arcnum);
	for(i=0;i<N.vexnum;++i)				/*输出网的顶点*/
		printf("%s ",N.vex[i]);
	printf("\n有向网N的:\n");			/*输出网N的弧*/
	printf("序号i=");
	for(i=0;i<N.vexnum;i++)
		printf("%11d",i);
	printf("\n");
	for(i=0;i<N.vexnum;i++)
	{
		printf("       %-6d   ",i);
		for(j=0;j<N.vexnum;j++)
			printf("%-11d",N.arc[i][j].adj);
		printf("\n"); 
	}
}
//用Floyd算法求有向网N的各顶点v和w之间的最短路径,当中path[v][w][u]表示u是从v到w当前求得最短路径上的顶点
void Floyd(MGraph N,PathMatrix path,ShortPathLength dist){
	int u,v,w,i;
	for(v=0;v<N.vexnum;v++)		//初始化数组path和dist
		for(w=0;w<N.vexnum;w++){
			dist[v][w]=N.arc[v][w].adj;	//初始时。顶点v到顶点w的最短路径为v到w的弧的权值
			for(u=0;u<N.vexnum;u++)
				path[v][w][u]=0;	//路径矩阵初始化为零
			if(dist[v][w]<INFINITY){	//假设v到w有路径,则由v到w的路径经过v和w两点
				path[v][w][v]=1;
				path[v][w][w]=1;
			}
		}
	for(u=0;u<N.vexnum;u++)
		for(v=0;v<N.vexnum;v++)
			for(w=0;w<N.vexnum;w++)
				if(dist[v][u]<INFINITY&&dist[u][w]<INFINITY&&(dist[v][u]+dist[u][w]<dist[v][w])){	//从v经u到w的一条路径为当前最短的路径
					dist[v][w]=dist[v][u]+dist[u][w];	//更新v到w的最短路径
					for(i=0;i<N.vexnum;i++) 	//从v到w的路径经过从v到u和从u到w的全部路径
						path[v][w][i]=path[v][u][i]||path[u][w][i];
				}
}
void main(){
	int w,u,v,vnum=3,arcnum=4;
	MGraph N;
	GNode value[]={{0,1,5},{1,0,10},{1,2,6},{2,0,9}};
	VertexType ch[]={"v0","v1","v2"};
	PathMatrix path;						/*用二维数组存放最短路径所经过的顶点*/
	ShortPathLength dist;					/*用一维数组存放最短路径长度*/
	CreateGraph(&N,value,vnum,arcnum,ch); /*创建有向网N*/
	for(v=0;v<N.vexnum;v++)
		N.arc[v][v].adj=0;				/*弗洛伊德算法要求对角元素值为0。由于两点同样,其距离为0 */
	DisplayGraph(N);					/*输出有向网N*/
	Floyd(N,path,dist);
	printf("顶点之间的最短路径长度矩阵dist:\n");
	for(u=0;u<N.vexnum;u++)
	{
		for(v=0;v<N.vexnum;v++)
			printf("%6d",dist[u][v]);
		printf("\n");
	}
	for(u=0;u<N.vexnum;u++)
		for(v=0;v<N.vexnum;v++)
			if(u!=v)
				printf("%s到%s的最短距离为%d\n",N.vex[u],N.vex[v],dist[u][v]);
	printf("各顶点之间的最短路径所经过的顶点:\n");
	for(u=0;u<N.vexnum;u++)
		for(v=0;v<N.vexnum;v++)
			if(u!=v)
			{
				printf("由%s到%s经过:",N.vex[u],N.vex[v]);
				for(w=0;w<N.vexnum;w++)
					if(path[u][v][w]==1)
						printf("%s ",N.vex[w]);
				printf("\n");
			}
	system("pause");
}