//图--肇庆学院
//首先用结构体存储各个学校的建筑等
//再建立图---使用无向图----图存储路径长度
//目的:方便参观肇庆学院的最短路径 输入各个景点
//给输入 一个图:参观各个景点的最短路径【邻接矩阵】
//额外功能:平面图增加或删除景点或边(路径),修改边值
#include<stdio.h>
#include<stdlib.h>
#include<iostream>
using namespace std;
#pragma warning(disable:4996)
#define Maxnn 50
#define INFINITY 3213123//未被赋值,当成无穷大
int visited[50];//用于标识顶点是否已经访问过
int Menu();//初始页面
typedef struct view
{
int position;//景点编号
char name[32];//景点名称
char introduction[100];//景点介绍
}View;
typedef struct mgraph
{
View vexs[Maxnn];//顶点
int arcnum, vexnum;//边数与顶点数
int arcs[Maxnn][Maxnn];//邻接矩阵
}mgraph;
mgraph campus;
int Menu();//主菜单
mgraph Init();//初始景点信息
void IntroductionCampus(mgraph g);//介绍肇庆学院景点
void dispath(int dist[], int path[], int s[], int n, int v, mgraph g);//输出Dijkstra
void FromBeginToSth_Dijkstra(mgraph g);//采用Dijkstra展现某一景点到各个景点的最短路径
void ppath(int path[][Maxnn], int a, int b, mgraph g);//
void dispath_floyd(int A[][Maxnn], int path[][Maxnn], int n, mgraph g);//输出floyd
void InquireAToB_shortest(mgraph g);//采用floyd来展现 某一景点到 另一景点的最短路径
void PrintfCampus(mgraph g);//输出邻接矩阵(存着各路径长)
int locatevex(mgraph g, int v);//根据景点编号获得景点的序列
int ChangeGraph(mgraph* g);//进入改变图的页面
int creatgraph(mgraph* g);//建立新图
int DeleteVex(mgraph* g);//删除顶点
int DeleteArc(mgraph* g);//删除边
int AddVex(mgraph* g);//增添顶点
int AddArc(mgraph* g);//增添边
int FixGraph(mgraph* g);//修改图
int main();//主函数
int Menu()
{
int n;
char c;
printf("\n\n\t==============实验:肇庆学院一日游==============\n");
printf("\n\t1.学校景点介绍");
printf("\n\t2.查看到各个景点浏览路线");//采用 Dijkstra ,根据用户输入的起始景点编号,求出该景点到其他景点的最短路径线路以及距离
printf("\n\t3.查询景点间最短路径");//采用 Floyd,输入起始景点以及目的地景点编号,查询任意两个景点之间的最短路径线路以及距离
printf("\n\t4.更改景点的信息");
printf("\n\t5.打印邻接矩阵");
printf("\n\t0.退出");
do
{
fflush(stdin);
printf("\n\n\t请输入数字0-8选择功能:");
c = getchar();
n = c - 48;
/*if (n < 0 || n>7)
printf("\t\t\t输入选项错误!请重新输入选项");*/
} while (n < 0 || n>5);
return n;
}
mgraph Init()
{
mgraph c;
int i, j;
i = j = 0;
c.vexnum = 27;
c.arcnum = 38;
for (i = 0; i < c.vexnum; i++)
{
c.vexs[i].position = i;//依次给各个景点编号
}
strcpy(c.vexs[0].name, "办公大楼");
strcpy(c.vexs[0].introduction, "进入肇庆学院正前方便可看到");
strcpy(c.vexs[1].name, "中巴软件大楼");
strcpy(c.vexs[1].introduction, "旧计算机学院");
strcpy(c.vexs[2].name, "实训大楼");
strcpy(c.vexs[2].introduction, "新计算机学院,1楼有羽毛球场");
strcpy(c.vexs[3].name, "实验大楼");
strcpy(c.vexs[3].introduction, "电子学院");
strcpy(c.vexs[4].name, "体育馆");
strcpy(c.vexs[4].introduction, "共3楼,一楼有乒乓球场,二楼有篮球场");
strcpy(c.vexs[5].name, "游泳馆");
strcpy(c.vexs[5].introduction, "夏天开放,一次10块,办卡8块");
strcpy(c.vexs[6].name, "艺术楼");
strcpy(c.vexs[6].introduction, "有一片大空地是滑板爱好者与轮滑爱好者的天堂");
strcpy(c.vexs[7].name, "理工大楼");
strcpy(c.vexs[7].introduction, "是环化与制药、生科学院的大楼");
strcpy(c.vexs[8].name, "翰墨池");
strcpy(c.vexs[8].introduction, "肇庆学院最出名之处,池中有天鹅");
strcpy(c.vexs[9].name, "行知湖");
strcpy(c.vexs[9].introduction, "有种宁静的氛围,是艺术生的天堂");
strcpy(c.vexs[10].name, "第一运动场");
strcpy(c.vexs[10].introduction, "各路运动爱好者集聚于此");
strcpy(c.vexs[11].name, "第二运动场");
strcpy(c.vexs[11].introduction, "院运会开展的地方,但平时比较少人关顾");
strcpy(c.vexs[12].name, "第一饭堂");
strcpy(c.vexs[12].introduction, "比较普通,但二楼是教师饭堂");
strcpy(c.vexs[13].name, "第二饭堂");
strcpy(c.vexs[13].introduction, "比较好吃,但同时价格也比较昂贵");
strcpy(c.vexs[14].name, "第三饭堂");
strcpy(c.vexs[14].introduction, "价格实惠,关顾人数偏多,三楼有着超市");
strcpy(c.vexs[15].name, "第四饭堂");
strcpy(c.vexs[15].introduction, "三楼比较豪华,内置大屏幕有比赛的时候可以观看");
strcpy(c.vexs[16].name, "福慧图书馆");
strcpy(c.vexs[16].introduction, "肇庆学院内比较大型的图书馆,氛围很好");
strcpy(c.vexs[17].name, "严宽裕图书馆");
strcpy(c.vexs[17].introduction, "相对福慧图书馆规模要小一些");
strcpy(c.vexs[18].name, "紫荆苑");
strcpy(c.vexs[18].introduction, "公主楼纯住女生,住宿费很便宜但配置也差些");
strcpy(c.vexs[19].name, "榕华苑1");
strcpy(c.vexs[19].introduction, "公主楼纯住女生,住宿费正常1300一个月");
strcpy(c.vexs[20].name, "紫荆书院");
strcpy(c.vexs[20].introduction, "很豪华6人间有电梯");
strcpy(c.vexs[21].name, "榕华苑2");
strcpy(c.vexs[21].introduction, "巨豪华4人间有电梯");
strcpy(c.vexs[22].name, "博学书院");
strcpy(c.vexs[22].introduction, "男女混住楼下有篮球场");
strcpy(c.vexs[23].name, "力行书院");
strcpy(c.vexs[23].introduction, "男女混住,靠近第二运动场");
strcpy(c.vexs[24].name, "厚德书院");
strcpy(c.vexs[24].introduction, "男女混住,出门便有篮球场靠近校门口");
strcpy(c.vexs[25].name, "教师活动中心");
strcpy(c.vexs[25].introduction, "里面可以玩桌球、乒乓球等");
strcpy(c.vexs[26].name, "生物园");
strcpy(c.vexs[26].introduction, "里面有许多植物和鱼");
for (i = 0; i < c.vexnum; i++)
{
for (j = 0; j < c.vexnum; j++)
{
c.arcs[i][j] = INFINITY;//初始化
if (i == j)
{
c.arcs[i][j] = 0;
}
}
}
c.arcs[0][2] = 50; c.arcs[0][3] = 60; c.arcs[1][4] = 90;
c.arcs[2][3] = 60; c.arcs[2][8] = 40; c.arcs[3][4] = 60;
c.arcs[3][6] = 40; c.arcs[4][5] = 70; c.arcs[4][9] = 70; c.arcs[4][10] = 80;
c.arcs[4][17] = 200; c.arcs[5][7] = 70; c.arcs[6][9] = 40;
c.arcs[7][18]= 190; c.arcs[8][11] = 50;
c.arcs[9][12] = 40; c.arcs[10][18] = 70; c.arcs[11][12] = 60;
c.arcs[11][14] = 50; c.arcs[11][15] = 50; c.arcs[12][16] = 50; c.arcs[13][14] = 40;
c.arcs[13][22] = 60; c.arcs[14][15] = 50; c.arcs[14][20] = 90; c.arcs[15][16] = 60;
c.arcs[15][21] = 40; c.arcs[16][17] = 60; c.arcs[17][18] = 80; c.arcs[18][19] = 60;
c.arcs[20][21] = 60; c.arcs[20][24] = 80; c.arcs[22][23] = 60; c.arcs[22][25] = 80;
c.arcs[23][24] = 60; c.arcs[24][26] = 100; c.arcs[25][26] = 100;
for (i = 0; i < c.vexnum; i++) {//因为对称,所以将其补充完毕
for (j = 0; j < c.vexnum; j++)
c.arcs[j][i] = c.arcs[i][j];
}
return c;
}
void IntroductionCampus(mgraph g)
{
for (int i = 0; i < g.vexnum; i++)
{
printf("%d %s %s\n", g.vexs[i].position, g.vexs[i].name, g.vexs[i].introduction);
}
}
void dispath(int dist[], int path[], int s[], int n, int v,mgraph g)
{
int i, k,j;
for (i = 0; i < n; i++)
{
if (s[i] == 1) {
k = i;
printf("v%d.%s 到 v%d.%s的最短路径为:",g.vexs[v].position, g.vexs[v].name, g.vexs[i].position, g.vexs[i].name);
if (k == v)
{
printf("%d.%s", k, g.vexs[k].name);
}
while (k != v)
{
printf("v%d.%s<--", k,g.vexs[k].name);
k = path[k];
}
printf("v%d.%s \n路径长度为:%d\n",g.vexs[v].position, g.vexs[v].name, dist[i]);
}
}
}
void FromBeginToSth_Dijkstra(mgraph g)
{
int v;
printf("请输入起始位置(编号):");
scanf("%d", &v);
while (v<0 || v>g.vexnum)
{
printf("您输入的编号不正确,请重新输入");
return;
scanf("%d", &v);
}
int dist[Maxnn], path[Maxnn];
int s[Maxnn];//标记已经找到的最短路径的顶点
int i, j, k;
int mindis;
for (i = 0; i < g.vexnum; i++)
{
dist[i] = g.arcs[v][i];//距离初始化
s[i] = 0;//0表示未找到最短路径
if (dist[i] < INFINITY)//路径初始化,即 最开始的路径设为起始位置
path[i] = v;
else
path[i] = -1;
}
s[v] = 1;//即起始位置最短路径 为 本身
for (i = 0; i < g.vexnum; i++)//对剩余顶点遍历,直到求出v到其余所有顶点的最短路径
{
mindis = INFINITY;
k = v;
for (j = 0; j < g.vexnum; j++)//选出V的边权重和最短的点,并且未被设置未最短路径
{
if (s[j] == 0 && dist[j] < mindis)
{
k = j; //最短的那个点
mindis = dist[j];//最短的权重即路径
}
}
s[k] = 1;//将该点设为最短路径点
for (j = 0; j < g.vexnum; j++)//修改V到该点的路径长
{
if (s[j] == 0 && g.arcs[k][j] < INFINITY && dist[k] + g.arcs[k][j] < dist[j])//当前点到原点+当前点到下一个点<原点到下一个点
{
dist[j] = dist[k] + g.arcs[k][j];
path[j] = k;
}
}
}
dispath(dist, path, s, g.vexnum, v,g);//输出最短路径
}
void ppath(int path[][Maxnn], int a, int b,mgraph g)
{
int k;
k = path[a][b];
if (k == -1)//a到b直达
{
printf("v%d.%s->",g.vexs[b].position, g.vexs[b].name);
}
else
{
ppath(path, a, k, g);
//printf("v%s->",g.vexs[k].name);
ppath(path, k, b, g);
}
}
void dispath_floyd(int A[][Maxnn], int path[][Maxnn], int n,mgraph g)
{
int a, b;
printf("请输入起始点与目的地:");
scanf("%d %d", &a, &b);
printf("\n");
while (a >= g.vexnum || b >= g.vexnum)
{
printf("输入有误请重新输入:");
scanf("%d %d", &a, &b);
}
if (A[a][b] == INFINITY)
{
if (a != b)
{
printf("从v%d.%s到v%d.%s没有路径\n", g.vexs[a].position, g.vexs[a].name,g.vexs[b].position, g.vexs[b].name);
}
}
else
{
printf("从v%d.%s到v%d.%s路径为:",g.vexs[a].position,g.vexs[a].name,g.vexs[b].position, g.vexs[b].name);
printf("v%d.%s->",g.vexs[a].position, g.vexs[a].name);
ppath(path, a, b,g);
printf("路径长度为:%d\n", A[a][b]);
}
}
void InquireAToB_shortest(mgraph g)
{
int A[Maxnn][Maxnn];//存储路径长
int path[Maxnn][Maxnn];//存储中间点
int i, j, v;
for (i = 0; i < g.vexnum; i++) //初始化
{
for (j = 0; j < g.vexnum; j++)
{
A[i][j] = g.arcs[i][j];
path[i][j] = -1;
}
}
for (v = 0; v < g.vexnum; v++) //依次加入中间点
{
for (i = 0; i < g.vexnum; i++)//行
{
for (j = 0; j < g.vexnum; j++)//列
{
if (A[i][j] > A[i][v] + A[v][j])
{
A[i][j] = A[i][v] + A[v][j];//更新最短路径
path[i][j] = v;//更新存储中间点
}
}
}
}
dispath_floyd(A,path, g.vexnum,g);//输出最短路径
}
void PrintfCampus(mgraph g)
{
int i, j;
for (i = 0; i < g.vexnum; i++)
{
for (j = 0; j < g.vexnum; j++)
{
if (g.arcs[i][j] == INFINITY)
{
printf("- ");
}
else
printf("%d ", g.arcs[i][j]);
}
printf("\n");
}
}
int locatevex(mgraph g, int v)
{
int i;
for (i = 0; i < g.vexnum; i++)
{
if (v == g.vexs[i].position)
return i;
}
return -1;
}
int creatgraph(mgraph * g)
{
int i, j;
int v0, v1, distance;
int m, n;
printf("请输入图的顶点数与边数:\n");
scanf("%d %d", &g->vexnum, &g->arcnum);
printf("下面请输入景点信息:\n");
for (i = 0; i < g->vexnum; i++)
{
printf("请输入景点编号:");
scanf("%d", &g->vexs[i].position);
printf("\n请输入景点名称:");
scanf("%s", g->vexs[i].name);
printf("\n请输入景点介绍:");
scanf("%s", g->vexs[i].introduction);
}
for (i = 0; i < g->arcnum; i++)
{
for (j = 0; j < g->arcnum; j++)
if (i == j)
g->arcs[i][j] = 0;
else
g->arcs[i][j] = INFINITY;
}
printf("\n下面输入景点边的信息:");
for (i = 1; i <= g->arcnum; i++)
{
printf("\n输入景点的起始点、终点与长度为:");
scanf("%d%d%d", &v0, &v1, &distance);
m = locatevex(campus, v0);
n = locatevex(campus, v1);
if (m >= 0 && n >= 0)
{
g->arcs[m][n] = distance;
g->arcs[n][m] = g->arcs[m][n];
}
}
return 1;
}
int DeleteVex(mgraph* g)
{
int i, j;
int m;
int v;
if (g->vexnum < 0)
{
printf("图中已无顶点\n");
}
printf("请输入想要删除的景点编号:");
scanf("%d", &v);
while (v<0 || v>g->vexnum)
{
printf("输入有误请重新输入:");
scanf("%d", &v);
}
m = locatevex(campus, v);
if (m < 0)
{
printf("该顶点已经删除");
return 1;
}
for (i = m; i < g->vexnum-1; i++)
{
g->vexs[i].position = g->vexs[i+1].position;
strcpy(g->vexs[i].name,g->vexs[i + 1].name) ;
strcpy(g->vexs[i].introduction, g->vexs[i+1].introduction);
}
for (i = m; i < g->arcnum-1; i++)
{
for (j = 0; j < g->arcnum; j++)
{
g->arcs[i][j] = g->arcs[i + 1][j];
g->arcs[j][i] = g->arcs[i][j];
}
}
g->vexnum--;
return 1;
}
int DeleteArc(mgraph* g)
{
int v0, v1;
int m,n;
if (g->arcnum < 0)
{
printf("图中已无边可删");
return 1;
}
printf("请输入要删除边的起始点与终点:");
scanf("%d %d", &v0, &v1);
m = locatevex(campus, v0);
if (m < 0)
{
printf("该顶点已经被删除");
return 1;
}
n = locatevex(campus, v1);
if (n < 0)
{
printf("该顶点已经被删除");
return 1;
}
g->arcs[m][n] = INFINITY;
g->arcs[n][m] = INFINITY;
g->arcnum--;
return 1;
}
int AddVex(mgraph* g)
{
int m, v;
int i, j;
printf("请输入要新增景点的信息:");
printf("景点编号:");
scanf("%d", &g->vexs[g->vexnum].position);
printf("景点名称:");
scanf("%s", g->vexs[g->vexnum].name);
printf("景点介绍:");
scanf("%s", g->vexs[g->vexnum].introduction);
g->vexnum++;
for (i = 0; i < g->vexnum; i++)
{
g->arcs[i][g->vexnum - 1] = INFINITY;
g->arcs[g->vexnum - 1][i] = INFINITY;
}
return 1;
}
int AddArc(mgraph* g)
{
int v0, v1;
int distance;
printf("\n请输入边的起始点与终点、边长:");
scanf("%d%d%d", &v0, &v1, &distance);
while (v0<0 || v0>g->vexnum || v1<0 || v1>g->vexnum)
{
printf("输入错误,重新输入:");
scanf("%d%d", &v0, &v1);
}
if (locatevex(campus, v0) < 0)
{
printf("此结点已经删除");
return 1;
}
if (locatevex(campus, v1) < 0)
{
printf("此结点已经删除");
return 1;
}
g->arcs[v0][v1] = distance;
g->arcs[v1][v0] = distance;
return 1;
}
int FixGraph(mgraph* g)
{
int changenum;
int i, j;
int m,n;
int v0, v1, distance;
printf("请输入要修改的景点个数:");
scanf("%d", &changenum);
while (changenum < 0 || changenum > g->vexnum)
{
printf("输入有误请重新输入:");
scanf("%d", &changenum);
}
for (i = 0; i < changenum; i++)
{
printf("\n请输入景点编号:");
scanf("%d", &m);
n = locatevex(campus, m);
printf("\n请输入景点的名称:");
scanf("%s", g->vexs[n].name);
printf("\n请输入景点的简介:");
scanf("%s", g->vexs[n].introduction);
}
printf("\n下面请输入要修改的边数:");
scanf("%d", &changenum);
while (changenum < 0 || changenum > g->vexnum)
{
printf("输入有误请重新输入:");
scanf("%d", &changenum);
}
for(i = 0;i<changenum;i++)
{
printf("\n修改的第%d条边的起点 终点 长度为:", i+1);
scanf("%d %d %d", &v0, &v1, &distance);
m = locatevex(campus, v0);
n = locatevex(campus, v1);
if (m >= 0 && n >= 0)
{
g->arcs[m][n] = distance;
g->arcs[n][m] = distance;
}
}
return 1;
}
int ChangeGraph(mgraph * g)
{
int choice;
printf("\n 请问是要\n\n (1)再次建图 (2)删除结点 (3)删除边 \n");
printf("\n (4)新增结点 (5)增加边 (6)更新信息 \n");
printf("\n (7)打印邻接矩阵 (8)返回?\n\n");
scanf("%d", &choice);
printf("\n");
while (!(choice == 1 || choice == 2 || choice == 3 || choice == 4 || choice == 5 || choice == 6 || choice == 7 || choice == 8))
{
printf("输入选择不明确,请重输\n");
scanf("%d", &choice);
}
while (1)
{
switch (choice)
{
case 1:creatgraph(g); break; //重建图
case 2:DeleteVex(g); break;//删除顶点
case 3:DeleteArc(g); break;//删除边
case 4:AddVex(g); break;//新增结点
case 5:AddArc(g); break;//增加边
case 6:FixGraph(g); break;//修改图
case 7:PrintfCampus(campus); break;//输出邻接矩阵
case 8:return 1; //返回主菜单
}
printf("\n 请问是要\n\n (1)再次建图 (2)删除结点 (3)删除边 \n");
printf("\n (4)新增结点 (5)增加边 (6)更新信息 \n");
printf("\n (7)打印邻接矩阵 (8)返回?\n\n");
scanf("%d", &choice);
while (!(choice == 1 || choice == 2 || choice == 3 || choice == 4 || choice == 5 || choice == 6 || choice == 7 || choice == 8))
{
printf("输入选择不明确,请重输\n");
scanf("%d", &choice);
}
}
}
int main()
{
int n;
int select;
campus = Init();//初始化校园信息
//mgraph school = campus;
do {
system("cls");
select = Menu();
switch (select)
{
case 1://学院景点介绍
IntroductionCampus(campus);
break;
case 2://查看浏览路线 输入位置,输出该位置到其他位置的路线
FromBeginToSth_Dijkstra(campus);//Dijkstra,求某个顶点到其余各顶点的最短路径
break;
case 3://查询景点间最短路径 Floyd算法
InquireAToB_shortest(campus);
break;
case 4://更改图的信息
ChangeGraph(&campus);
break;
case 5:打印学校平面图
PrintfCampus(campus);
break;
case 0://退出
break;
}
printf("\n\n");
system("pause");
} while (select != 0);
return 0;
}