#include<string> 
#include "LinkQueue.h"
#include "Mgraph.h"
#include <iostream>
using namespace std;

const MAX_ARCNUM=50;

//算法6.20 Dijkstra算法
template<class DT>
void ShortestPath_DIJ(MGraph<DT> G, int v0)				// 从顶点v开始计算的最小生成树
{
	int v,i,w,min;
    bool S[MAX_VEXNUM]={false};							// 记载S集合中的顶点
    int D[MAX_VEXNUM];									// 源点到其它各顶点的距离
	int P[MAX_VEXNUM]={-1};								// 源点互其它各顶点的路径信息
	for(v=0;v<G.vexnum;v++)								// 初始化
	{
		S[v]=false;										// 
		D[v]=G.arcs[v0][v];
		if(D[v]<INF)									// 源点可直达顶点的距离
			P[v]=v0;
		else
			P[v]=-1;
	}
    D[v0]=0;											// 源点到自身的距离为0
	S[v0]=true;	
	for(i=1;i<G.vexnum;i++)								// 求n-1条最短路径
	{
		min=INF;
		for(w=0;w<G.vexnum;++w)							// 在源点到未选目的地顶点距离中选路径最小的顶点
			if(!S[w] && D[w]<min)
			{
				v=w; min=D[w];
			}
		S[v]=true;										// 加入S
		for(w=0;w<G.vexnum;++w)							// 考量经过新求出最短路径有否比原先路径短的
			if(!S[w]&&(D[v]+G.arcs[v][w]<D[w]))			// 如果有
			{
				D[w]=D[v]+G.arcs[v][w];					// 更新D[]值
				P[w]=v;									// 更新P[]值
			}
	}
	cout<<G.vexs[v0]<<"到其余各顶点的距离为："<<endl;   // 输入D[]
	for(w=0;w<G.vexnum;w++)
			cout<<D[w]<<"  ";
	cout<<"\n路径距径P为："<<endl;						// 输出P[]
	for(w=0;w<G.vexnum;w++)
		cout<<P[w]<<"  ";
	cout<<endl;
}

// 算法6.21 Floyd算法
template <class DT>
void ShortestPath_Floyd(MGraph<DT> G)					// 返回生成代价
{
	int k,i,j;
	int D[MAX_VEXNUM][MAX_VEXNUM];						// D[i][j]表示顶点i和顶点j的最短距离
	int P[MAX_VEXNUM][MAX_VEXNUM];						// 记载最短距离的路径信息
	for(i=0;i<G.vexnum;i++)								// 初始化D[][]
		for(j=0;j<G.vexnum;j++)
		{
			
			// 初始化P[][]
			//if(i==j)
				//D[i][j]=0;
			if(D[i][j]<INF && i!=j)						// 顶点 i 和顶点 j 之间存在路径
				P[i][j]=i;
			else P[i][j]=-1;							// 顶点 i 和顶点 j 之间不存在路径
		}											
	cout<<"\nD-1和P-1:"<<endl;							// 显示D、P
	DispPath_Floyd(D,G.vexnum,P);

	for(k=0;k<G.vexnum;k++) //以k为中间点对所有顶点对{i,j}进行检测
	{
		for(i=0;i<G.vexnum;i++)
		{
			for(j=0;j<G.vexnum;j++)
			{    
				if(i!=j && D[i][k]+D[k][j]<D[i][j])		// 如果满足修改条件
				{   
					D[i][j]=D[i][k]+D[k][j];			// 修改D[i][j]
					P[i][j]=P[k][j];					// 修改路径
				}
			}
		}
		cout<<"\n第"<<k+1<<"次替代后的D和P"<<endl;
		DispPath_Floyd(D,G.vexnum,P);
	}

}

void DispPath_Floyd(int D[][MAX_VEXNUM],int n,int P[][MAX_VEXNUM]) // 距离信息和路径信息显示
{
	int i,j;
	cout<<"\nD:"<<endl;
	for(i=0;i<n;i++)												// 输出第一趟D[]
	{
		for(j=0;j<n;j++)
			cout<<D[i][j]<<'\t';
		cout<<endl;
	}
	cout<<"\nP:"<<endl;
	for(i=0;i<n;i++)											// 输出第一趟D[]
	{
		for(j=0;j<n;j++)
			cout<<P[i][j]<<'\t';
		cout<<endl;
	}
}



void DispMenu()
{
	cout<<"\n如果不创建图，可使用测试图!"<<endl;
	cout<<"\n 请选择你要的操作"<<endl;
	cout<<" 1. " <<endl;
	cout<<"  2. 建立有向网Dijkstra算法" <<endl;
	cout<<" 3. Floyd算法" << endl;
	cout<<" 4. 显示网"<< endl;
	cout<<" 0. 退出"<< endl;
}

bool visited[MAX_VEXNUM]={false};

void main()
{
	int i,j,v0;
	char w;
	MGraph<char> G,G1,G2;
	G1.vexnum=5;												// Dijkstra算法测试图
	G1.arcnum=7;
	G1.vexs[0]='A';G1.vexs[1]='B';G1.vexs[2]='C';
	G1.vexs[3]='D';G1.vexs[4]='E';
	for(i=0;i<G1.vexnum;i++)								   // 邻接矩阵初始化
		for(j=0;j<G1.vexnum;j++)
			G1.arcs[i][j]=INF;
	G1.arcs[0][1]=10;
	G1.arcs[0][3]=50;
	G1.arcs[0][4]=45;
	G1.arcs[1][4]=30;
	G1.arcs[3][4]=15;
	G1.arcs[1][2]=4;
	G1.arcs[2][4]=11;
    cout<<"\n测试图为G1："<<endl;
	DispG(G1);

	G2.vexnum=3;												// Floyd算法测试图
	G2.arcnum=5;
	G2.vexs[0]='A';G2.vexs[1]='B';G2.vexs[2]='C';
	for(i=0;i<G2.vexnum;i++)								   // 邻接矩阵初始化
		for(j=0;j<G2.vexnum;j++)
			G2.arcs[i][j]=INF;
	G2.arcs[0][1]=4;
	G2.arcs[1][0]=6;
	G2.arcs[0][2]=11;
	G2.arcs[2][0]=3;
	G2.arcs[1][2]=2;
    cout<<"\n测试图为G2："<<endl;
	DispG(G2);
	
	bool f=false;											// 是否创建网，缺省为未创建                                    	
	int choice;
	do
	{
		DispMenu();
		cin>>choice;
		switch(choice)
		{
			case 1:														// 创建无向网
				    f=true;
					CreateDN(G);
					cout<<endl;
					cout<<"创建的有向网为："<<endl;
					DispG(G);
					break;
			case 2:														// Dijkstra算法
					cout<<"请输入起始计算顶点:  ";
					cin>>w;
					v0=LocateVex(G1,w);
					if(v0==-1)
						cout<<"顶点不存在！"<<endl;
					else
					{
						if(!f)											// 使用测试图                                        
							ShortestPath_DIJ(G1,v0);
						else
							ShortestPath_DIJ(G,v0);
					}
					break;
			case 3:														// Floyd算法
					if(!f)												// 使用测试图
						ShortestPath_Floyd(G2);
					else
						ShortestPath_Floyd(G);
					cout<<endl;
					break;
			case 4:														// 显示网
					DispG(G);
					cout<<endl;
					break;
			case 0:
					cout<<"结束运行，Bye-Bye!"<<endl;
					break;
			default:
					cout<<"无效选择，请重选!"<<endl;
			}//case
		}while(choice!=0);
}//main
		 