#include <iostream.h>
#include <cstring>
#include <stdlib.h>
#include<stdio.h>
#include <conio.h>
#include <ctype.h>
#define MAXVTXNUM  20  //图中顶点数的最大值
#define MAXSIZE    1000
#define MAX        30
#ifndef  x
#define  x 1
typedef struct 
{
    char *name;  //该顶点的名称
    char *info;  //景点信息
}VertexType;     //顶点类型
#endif
#ifndef xx
#define xx 1
typedef struct
{
    int lengh;    //边的权值
    int ivex,jvex; //边两端的顶点号
}EdgeType;  // 变的类型
#endif
#ifndef xxx
#define xxx 1
typedef struct EdgeNode
{
    EdgeType elem;  
    EdgeNode *ilink,*jlink;
}EdgeNode, *EdgePtr; //边的结点类型
#endif
#ifndef xxxx
#define xxxx  1 
typedef struct
{
    VertexType data;  
    EdgePtr firstEdge;  //指向第一条依附于该顶点的边的指针类型
}VNode; //顶点类型
#endif
#ifndef xxxxx
#define xxxxx  2
typedef struct
{
    VNode Adjmulist[MAXVTXNUM]; //邻接多重表
    int vexNum, edgeNum; //图中的顶点数和边数
}GraphType;  //图的类型
#endif
#ifndef xxxxxx
#define xxxxxx 3
typedef struct
{
    int vx, vy;
}Edge;
typedef struct
{
    Edge edges[MAXVTXNUM];  //路径中边的序列
    int len; //路径中边的数目
}PathType;
#endif
#ifndef xxxxxxx 
#define xxxxxxx  4
typedef struct
{
    char *Vertices[MAXSIZE]; //路径中景点的序列 
    int num;
}PType;
#endif
void InitGraph(GraphType &g); //初始化邻接多重表,表示一个空图
//在途中查找其景点名和uname相同的顶点。若存在,则以i返回其在临界多重表中的位置并返回TURE;
bool LocateVex(GraphType &g, char *uname, int &i); 
void GetVex(GraphType g, int i, VertexType &v); 
EdgePtr FirstEdge(GraphType g, int vi);
void NextEdge(GraphType g, int vi, EdgePtr p, int &vj, EdgePtr &q); 
void InsertVex(GraphType &g, VertexType v); 
void InsertEdge(GraphType &g, EdgeType e);
void DeleteVex(GraphType &g, VertexType v);
void DeleteEdge(GraphType &g, EdgeType e);
void InitPath(PathType &pa);  //初始化pa为一条空路径
void CopyPath(PathType &p1, PathType &p2);  //复制路径p1=p2
void InsertPath(PathType &pa, int v, int w);  //在路径pa中插入一条边(v,w)
int PathLength(PathType pa);   //返回路径pa的长度
void OutPath(GraphType g, PathType pa, PType &vtxes);  //将路径转化为景点的名序列
void Initialization();
void ReadCommand(char &cmd);
void Interpret(char cmd);
void CreatGraph(GraphType &g, FILE *f);
void GetShortestPath(GraphType g, char *sname, char *tname,
                     int &pathLength, PType &PathInfo);
void ShortestPath(GraphType g, int st, int nd,
                  int &pathLength, PType &PathInfo);
//#include<string>
/////////////////////////////////////////////////////////////
//////////////////////   图设计部分   ///////////////////////
/////////////////////////////////////////////////////////////
void InitGraph(GraphType &g)
{
    g.vexNum = g.edgeNum = 0;
}//InitGraph
bool LocateVex(GraphType &g, char *uname, int &i)
{
    for(i=0; i<g.vexNum; i++)
        if(!strcmp(uname, g.Adjmulist[i].data.name))
        {
            return true;
            break;
        }
    return false;
}//LocateVex
EdgePtr FirstEdge(GraphType g, int vi)
{//返回图g中指向依附于顶点vi的第一条边的指针g.Adjmulist[i].data
    return
        g.Adjmulist[vi].firstEdge;
}//FirstEdge
void GetVex(GraphType g, int i, VertexType &v)
{
    if(i<0)
        cout<<"这两点间无路径可通!"<<endl;
    else
        v = g.Adjmulist[i].data;
}//GetVex
void NextEdge(GraphType g, int vi, EdgePtr p, int &vj, EdgePtr &q)
{
    if(p->elem.ivex==vi )
    {
        q = p->ilink;
        vj = p->elem.jvex;
    }
    else
    {
        q = p->jlink;
        vj = p->elem.ivex;
    }
}//NextEdge
void InsertEdge(GraphType &g, EdgeType e)
{
    
    EdgePtr p;
    p = (EdgePtr)malloc(sizeof(EdgeNode));
    p->elem =e;
    p->ilink = FirstEdge(g,e.ivex);
    p->jlink = FirstEdge(g, e.jvex);
    g.Adjmulist[e.ivex].firstEdge = g.Adjmulist[e.jvex].firstEdge = p;
}//InsertEdge
void InsertVex(GraphType &g, VertexType v, int i)
{ 
    //在图g的邻接多重表中添加一个顶点v
    g.Adjmulist[i].data.name = new char[MAXSIZE];
    g.Adjmulist[i].data.info = new char[MAXSIZE];
    strcpy(g.Adjmulist[i].data.name,v.name);
    strcpy(g.Adjmulist[i].data.info,v.info);
    g.Adjmulist[i].firstEdge = NULL;
}
///////////////////////////////////////////////////////////////////////
/////////////////////////   路径类型   ////////////////////////////////
///////////////////////////////////////////////////////////////////////
void InitPath(PathType &pa)
{ 
    pa.len = 0;
}//InitPath
int PathLengh(PathType pa)
{
    return pa.len;
}//PathLengh
void CopyPath(PathType &p1, PathType &p2)
{
    //复制路径p1=p2
    for(int i =0; i<p2.len; i++)
    {
        p1.edges[i].vx = p2.edges[i].vx;
        p1.edges[i].vy = p2.edges[i].vy;
    }
    p1.len = p2.len;
}//CopyPath
void InsertPath(PathType &pa, int v, int w)
{
    //在路pa径中插入一条边(v,w)
    pa.edges[pa.len].vx = v;
    pa.edges[pa.len].vy = w; 
    pa.len++;
}//InsertPath
void OutPath(GraphType g, PathType pa, PType &vtxes)
{
    //将路径转化为景点的名序列
    int m = 0;
    VertexType vtx;
    vtx.info = new char[MAXSIZE];
    vtx.name = new char[MAXSIZE];
    for(int i=0; i<pa.len; i++)
    {
        vtxes.Vertices[m] = new char[MAXSIZE];
        GetVex(g, pa.edges[i].vx, vtx);
        strcat(vtx.name,vtx.info);
         strcpy(vtxes.Vertices[m++], vtx.name);
    }
    GetVex(g, pa.edges[pa.len-1].vy, vtx);
    vtxes.Vertices[m] = new char[MAX];
    strcpy(vtxes.Vertices[m] , vtx.name);
    strcat(vtxes.Vertices[m] , vtx.info);
    vtxes.num = m;
}//OutPath
/////////////////////////////////////////////////////////
//////////////// 主程序部分//////////////////////////////
/////////////////////////////////////////////////////////
void Initialization(GraphType &ga)
{
    system("cls");
    FILE *fin = fopen("test.txt", "r");
    CreatGraph(ga, fin);
}//Initialization
void PrintScenery(char *sname, GraphType g)
{
    for(int j=0; j<g.vexNum;j++)
        if(!strcmp(sname,g.Adjmulist[j].data.name))
        {
            cout<<"输出的景点名为:"<<sname<<endl;
            cout<<"景点信息为: "<<g.Adjmulist[j].data.info<<endl;
            break;
        }
}//PrintScenery
void ReadCommand(char &cmd)
{
    do{      
          cout<<"读入操作符命令:(s/S/V/v/Q/q ?)" ;
          cin>>cmd;
    }
    while (cmd!='s'&& cmd!='S'&& cmd!='v'&& cmd!='V'&& cmd!='q'&& cmd!='Q');
}//ReadCommand
void PrintPath(PType spath, int pathlen)
{
        cout<<"输出所经历路径信息为:"<<endl;
        for(int i=0; i<spath.num; i++)
            cout<<"----"<<spath.Vertices[i]<<"----";
            cout<<endl;
            cout<<"所经历的最短路径长度为:"<<pathlen<<endl;
    
}//PrintPath
void Interpret(char cmd, GraphType g)
{
    char *sname=new char[MAXSIZE];
    char *tname=new char[MAXSIZE];
    int pathlen;
    PType spath;
    switch(cmd)
    {
    case 's':
        cout<<"读入景点名称: ";
        cin>>sname;
        PrintScenery(sname, g);
        break;
    case 'S':
        cout<<"读入景点名称: ";
        cin>>sname;
        PrintScenery(sname,g);
        break;
    case 'v':
        cout<<"读入起点名称: " ;
        cin>>sname;
        cout<<"读入终点名称:  ";
        cin>>tname;
        GetShortestPath(g, sname,tname,pathlen,spath);
        PrintPath(spath, pathlen);
        break;
    case 'V':
        cout<<"读入起点名称: " ;
        cin>>sname;
        cout<<"读入终点名称:  ";
        cin>>tname;
        GetShortestPath(g, sname,tname,pathlen,spath);
        PrintPath(spath, pathlen);
        break;
    case 'q':
            break;
    case 'Q':
            break;
    }
}//Interpret
void CreatGraph(GraphType &g, FILE *f)
{
    VertexType v;
    InitGraph(g);
    EdgeType e;
    v.info = new char[MAXSIZE];
    v.name = new char[MAXSIZE];
    fscanf(f,"%d",&g.edgeNum);
    fgetc(f);
    fscanf(f,"%d",&g.vexNum);
    for(int i=0; i<g.vexNum; i++)
    {
        fscanf(f, "%s",v.name);
        fgetc(f); 
        fscanf(f, "%s",v.info);
        InsertVex(g,v,i);
    }
    for(int k=0; k<g.edgeNum; k++)
    {
        fscanf(f,"%d",&e.ivex);
            fgetc(f);
        fscanf(f,"%d",&e.jvex);
            fgetc(f);
        fscanf(f,"%d",&e.lengh);
        if(e.lengh)
            InsertEdge(g,e);
    }
}//CreatGraph
void GetShortestPath(GraphType g, char *sname, char *tname,
                     int &pathLengh,PType &PathInfo)
{
    int sv,tv;
    LocateVex(g,sname,sv);
    LocateVex(g, tname, tv);
    ShortestPath(g,sv,tv,pathLengh,PathInfo);
}//GetShortestPath
void InitSet(bool *ss, GraphType g)
{
    for(int i=0; i<g.vexNum; i++)
        ss[i] = false;
}
void PutInSet(int st, bool ss[MAXVTXNUM])
{
    ss[st] = true;
}//PutInSet
int  minval(int *dist, GraphType g, bool *ss)
{    
    int min = -1;
    for(int i =0; i<g.vexNum; i++)
        if(!ss[i])
        {
           if(min == -1)
               min = i;
           else if(dist[min]>dist[i])
               min = i;
        }
    return min;
}//minval
bool InSet(int w, bool *ss)
{
    if(ss[w])
        return true;
    else
        return false;
}
void ShortestPath(GraphType g, int st, int nd, int &pathLengh,
                  PType &PathInfo)
{
    unsigned int maxint = 10000000;
    int dist[MAXVTXNUM];
    PathType path[MAXVTXNUM];
    int adjvex;
    bool ss[MAXVTXNUM];
    int min,v,w;
    int count=0;
    EdgePtr p,q;
    for(int i=0; i<g.vexNum; i++)
    {
        dist[i] = maxint;
        InitPath(path[i]);
    }
       p = FirstEdge(g, st);
    while(p)
    {
        NextEdge(g,st,p,adjvex,q);
        dist[adjvex] = p->elem.lengh;
        InsertPath(path[adjvex],st,adjvex);
        p = q;
    }
    bool found = false;
    InitSet(ss,g);
    PutInSet(st,ss);
    w = st;
    while(!found)
    {
        min = minval(dist,g,ss);
        if(min==nd)
        {
            InsertPath(path[nd],nd,w);
            found = true;
        }
        else
        {
            v = min;
            PutInSet(v,ss);
            p = FirstEdge(g,v);
            while(p)
            {
                NextEdge(g,v,p,w,q);
                if(!InSet(w,ss) && dist[v]+p->elem.lengh<dist[w])
                {
                    dist[w] = dist[v]+p->elem.lengh;
                    CopyPath(path[w], path[v]);
                    InsertPath(path[w], v, w);
                }
                p = q;
            }//while(p)
        }//else
    }//while(!found)
    pathLengh = dist[nd];
    OutPath(g, path[nd], PathInfo);
}//ShortestPath
//////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////
void main()
{
    
    GraphType ga;
    char cmd;
    Initialization(ga);
    cout<<"****************************************************************"<<endl;
    cout<<"*******     班级:030524班       学号:03051433         ********"<<endl;
    cout<<"*******     制作人:王甲楼       西安电子科技大学       ********"<<endl;
    cout<<"*****************    符命令注解:S/s表示显示   *****************"<<endl;
    cout<<"*****************     V/v表示开始查询最短路径   ****************"<<endl;
    cout<<"*****************     Q/q 表示退出              ****************"<<endl;
    cout<<"****************************************************************"<<endl;
    cout<<endl<<endl<<endl;
    do
    {
        ReadCommand(cmd);
        Interpret(cmd, ga);
    }
    while(cmd!= 'q' && cmd!='Q');
}//main
 ////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////



 
											





 
	    

 
	





