#include <iostream>
using namespace std;
#define MAXSIZE 100
#include<queue>
#include<stack>
/*dijkstra本质上的思想是贪心,它只适用于不含负权边的图.
我们把点分成两类,一类是已经确定最短路径的点,称为"白点",另一类是未确定最短路径的点,称为"蓝点"
dijkstra的流程如下::
1. 初始化dis[start] = 0,其余节点的dis值为无穷大.
2. 找一个dis值最小的蓝点x,把节点x变成白点.
3. 遍历x的所有出边(x,y,z),若dis[y] > dis[x] + z,则令dis[y] = dis[x] + z
4. 重复2,3两步,直到所有点都成为白点.
时间复杂度为O(n^2)*/
/*当所有边长都是非负数的时候,全局最小值不可能再被其他节点更新.所以在第2步中找出的蓝点x必然满足:dis[x]已经是起点到x的最短路径.
我们不断选择全局最小值进行标记和拓展,最终可以得到起点到每个节点的最短路径的长度*/
typedef struct{
string name;//景点名称;
int id;//代号
string Introduction;//简介
}ElemType;
typedef struct LNode
{
ElemType data[MAXSIZE];
int length;
}LNode,*List;
struct edge
{
int to;//终点序号
int w; //边的权值
int next;//与该边同起点的上一条边的编号
};
struct node
{
int w;
int pos;
bool operator <( const node &x )const
{
return x.w < w;
}
};
priority_queue<node> q;
int f[MAXSIZE];
edge e[MAXSIZE];
int head[MAXSIZE];//head[i]表示以 i 为起点的最后一条边的编号
int dis[MAXSIZE];//dis[i]表示起点到i的最短路径的长度
int cnt;
bool vis[MAXSIZE];//表示该点是否被访问过
void Init(List &L)
{
L=new LNode;
L->length=0;
}
void Modify(List &L,int num,ElemType e)
{
L->data[num]=e;
}
ElemType Search(List L,int num)
{
return L->data[num];
}
inline void add_edge( int u, int v, int d )
{
cnt++;
e[cnt].w = d;
e[cnt].to = v;
e[cnt].next = head[u];
head[u] = cnt;
}
inline void dijkstra(int s)
{
dis[s] = 0;
q.push( ( node ){0, s} );
while( !q.empty() )
{
node tmp = q.top();
q.pop();
int x = tmp.pos, d = tmp.w;
if( vis[x] )
continue;
vis[x] = 1;
int y;
for( int i = head[x]; i; i = e[i].next )
{
y= e[i].to;
if( dis[y] > dis[x] + e[i].w )
{
dis[y] = dis[x] + e[i].w;
if( !vis[y] )
{
q.push( ( node ){dis[y], y} );
f[y]=x;
}
}
}
}
}
int main()
{
cout<<"------------------------------"<<endl;
cout<<"校园导游咨询"<<endl;
cout<<"1、录入景点信息"<<endl;
cout<<"2、修改景点信息"<<endl;
cout<<"3、查询景点信息"<<endl;
cout<<"4、查询2个景点间的最短路径和长度"<<endl;
cout<<"5、退出"<<endl;
cout<<"------------------------------"<<endl;
List L;
Init(L);
while(true)
{
string a;
cin>>a;
if(a=="1")
{
cout<<"请输入景点数量、边的条数、景点信息、边的信息:"<<endl;
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++)
{
cout<<"请输入第"<<i<<"个景点的信息"<<endl;
cout<<"景点名称:";
cin>>L->data[i].name;
cout<<"代号:";
cin>>L->data[i].id;
cout<<"简介:";
cin>>L->data[i].Introduction;
L->length++;
dis[i] = 0x7fffffff;
}
for(int i=1;i<=m;i++)
{
cout<<"请输入第"<<i<<"条边的起点、终点、长度:";
int u,v,w;
cin>>u>>v>>w;
add_edge(u,v,w);
add_edge(v,u,w);
}
cout<<"景点信息录入成功"<<endl;
}
else if(a=="2")
{
ElemType e;
cout<<"请输入修改景点的代号:";
int number;
cin>>number;
cout<<"请重新输入景点信息:"<<endl;
cout<<"景点名称:";
cin>>e.name;
cout<<"代号:";
cin>>e.id;
cout<<"简介:";
cin>>e.Introduction;
Modify(L,number,e);
cout<<"景点信息修改成功"<<endl;
}
else if(a=="3")
{
cout<<"请输入要查询景点的代号:";
int number;
cin>>number;
ElemType e=Search(L,number);
cout<<"景点名称:"<<e.name<<endl;
cout<<"简介:"<<e.Introduction<<endl;
}
else if(a=="4")
{
cout<<"请输入2个景点的代号:";
int start,end;
cin>>start>>end;
dijkstra(start);
stack<int> s;
int e=end;
s.push(e);
while (e!=start)
{
int tmp=f[e];
s.push(tmp);
e=tmp;
}
cout<<"景点"<<start<<"到景点"<<end<<"的一条最短路径为:"<<endl;
while(!s.empty())
{
cout<<s.top()<<" ";
s.pop();
}
cout<<endl;
cout<<"最短路径的长度为:"<<dis[end]<<endl;
}
else{
break;
}
}
}
校园导游咨询
最新推荐文章于 2022-05-26 12:54:27 发布