实验目的
- 掌握基于邻接矩阵存储结构的有向网络的实现。
- 掌握有向网络的两类遍历算法。
- 掌握有向网络的单源最短路径算法(Dijkstra)。
- 掌握最短路径算法的应用:平分酒。
实验要求、内容
- 基于邻接矩阵存储结构实现有向网络的典型操作(构造、析构、增加顶点、删除顶点、增加弧、删除弧、查找 一个顶点、修改一个顶点、查找一个弧、修改一个弧、判空、判满、图中顶点个数、图中的弧个数、深度优先遍历、 广度优先遍历),测试和调试程序。 提示:用栈实现有向网络的深度优先遍历算法,用队列实现有向网络的广度优先遍历算法。
- 实现有向网络的单源最短路径算法,测试和调试程序。
- 使用有向网络的单源最短路径算法,解决“平分酒”问题,测试和调试程序。
实验设备
计算机、Windows 操作系统、C++语言集成开发环境。
实验指导
- 基于邻接矩阵存储结构实现有向网络的典型操作(构造、析构、增加顶点、删除顶点、增加弧、删除弧、查找 一个顶点、修改一个顶点、查找一个弧、修改一个弧、判空、判满、图中顶点个数、图中的弧个数、深度优先遍历、 广度优先遍历),测试和调试程序。注意:不要直接定义和使用一维数组和二维数组,请通过 new 操作和 delete 操作来申请或者释放一维数组与二维 数组的空间。实现完后,执行测试程序,逐一检验自己的 Network 类所有方法是否运行正常,给出运行截图并进行文字说明, 解释各截图中输出结果的含义。
- 掌握有向网络的单源最短路径算法(Dijkstra),测试和调试程序。
- 掌握最短路径算法的应用:平分酒。
Network.h
#ifndef NETWORK_H
#define NETWORK_H
#include <iostream>
#include <stack>
#include <queue>
#include <algorithm>
using namespace std;
enum Error_code { success, fail, range_error1, underflow, overflow, fatal, not_present, duplicate_error, entry_found, internal_error };
//三个模板参数:VertexType 为顶点数据类型,ArcType 为弧数据类型,graph_size 为预先设定的顶点个数
template <class VertexType, class ArcType, int graph_size>
class Network //有向网络
{
public:
Network(ArcType infinityArc);//infinityArc 为网络中初始的无穷大弧,邻接矩阵各元素的初始值
~Network();
void write();//以矩阵形式输出有向网络,调试时可以检查有向网络二维数组的值
//由于是通用类型的顶点和弧,所以在使用该类解决问题时可能需要完成输出运算符<<的重载
Error_code insertVertex(VertexType dataIn);//插入顶点,数据域为 dataIn
Error_code deleteVertex(VertexType dltKey, ArcType infinityArc);
//删除顶点,其数据域中为 dltKey,将该弧变为无穷大的断弧 infinityArc
Error_code insertArc(VertexType fromKey, VertexType toKey, ArcType newInfo, ArcType infinityArc);
//插入弧,该弧从 fromKey 指向 toKey,数据为 newInfo
Error_code deleteArc(VertexType fromKey, VertexType toKey, ArcType infinityArc);
//删除弧,该弧从 fromKey 指向 toKey,相当于将该弧置为无穷大的断弧 infinityArc
Error_code retrieveVertex(VertexType dataOut, int & i);
//查 DataOut 的顶点,返回该该顶点所在一维数组的位置 i
Error_code replaceVertex(VertexType dataOld, VertexType dataNew);
//查到 dataOld 的顶点,将其数据改为 dataNew
Error_code retrieveArc(VertexType fromKey, VertexType toKey, ArcType &dataOut);
//查找弧,该弧从 fromKey 指向 toKey,读出弧数据到 dataOut
Error_code replaceArc(VertexType fromKey, VertexType toKey, ArcType dataIn,ArcType infinityArc);
//修改弧,该弧从 fromKey 指向 toKey,新弧数据为 dataIn
VertexType getVertex(int i);//返回第 i 个顶点的数据域
ArcType getArc(int i, int j);//返回第 i 个顶点的第 j 个弧的数据域
bool empty();//叛图是否为空
bool full();//叛图是否为满
int sizeVertex(); //返回图顶点个数
int sizeArc(); //返回图弧的个数
int indegree(VertexType key, ArcType infinityAr); //返回顶点 key 的出度
int outdegree(VertexType key, ArcType infinityAr); //返回顶点 key 的入度
void depthFirst(void (*process)(VertexType dataProc), ArcType infinityArc);
//深度优先遍历(需要借助于栈),初始化时可能需要无穷大的断弧 infinityArc
void breadthFirst(void (*process)(VertexType dataProc), ArcType infinityArc);
//广度优先遍历(需要借助于队列),初始化时可能需要无穷大的断弧 infinityArc
Error_code shortestPathDistances(VertexType source, ArcType distance[], int prior[], ArcType zeroArc, ArcType infinityArc);
//求单源最短路径,source 为源顶点,distance 数组存储源顶点到所有顶点最短路径距离,
//prior 数组存储最短路径中各顶点的前驱顶点在一维数组的下标。
//zeroArc 为距离 0,infinityArc 为距离无穷大
protected:
int countVertex;//该有向网络的顶点个数
int countArc;//该有向网络的弧个数
//VertexType nodes[graph_size];//info for vertices
VertexType *nodes;//nodes 为一维数组,每个元素存储的是每个顶点的信息
//ArcType adjacency[graph_size][graph_size];//info for arcs
ArcType **adjacency;//adjacency 是二维数组,每个元素存储的是有向网络的弧的信息(如:权值)
//注意,在实现这个模板类时,为了考虑通用性,0 权值不要写成 0,无穷大权值不要直接写成一个具体的大整数,
//可以先分别写成 ArcType 类型的 zeroArc 和 infinityAr
typedef pair<int, int> PII;
};
#endif // NETWORK_H
Network.cpp
#include"Network.h"
template <class VertexType, class ArcType, int graph_size>
Network<VertexType, ArcType, graph_size>::Network(ArcType infinityArc)//构造函数
{
nodes = new VertexType[graph_size];//创建顶点数组
adjacency=new ArcType*[graph_size];//创建邻接矩阵
for(int i=0;i<graph_size;i++)
{
adjacency[i]=new ArcType[graph_size];//创建邻接矩阵
for (int j=0;j<graph_size;j++)
{
adjacency[i][j]=infinityArc;//其他节点的距离为无穷大
}
}
countVertex=0;
countArc=0;
}
template <class VertexType, class ArcType, int graph_size>
Network<VertexType, ArcType, graph_size>::~Network()//析构函数
{
delete[] nodes;
for(int i=0;i<graph_size;i++)
{
delete[] adjacency[i];
}
delete[] adjacency;
countVertex=0;
countArc=0;
}
template <class VertexType, class ArcType, int graph_size>
void Network<VertexType, ArcType, graph_size>::write()
//以矩阵形式输出有向网络,调试时可以检查有向网络二维数组的值
//由于是通用类型的顶点和弧,所以在使用该类解决问题时可能需要完成输出运算符<<的重载
{
cout<<"Network:"<<endl;
cout<<"顶点的个数为:"<<countVertex<<endl;
cout<<"顶点:\t";
for(int i=0;i<countVertex;i++)
{
cout<<nodes[i]<<'\t';//输出顶点
}
cout<<endl;
cout<<"弧的个数为:"<<countArc<<endl;
cout<<"弧:\t"<<endl;
for(int i=0;i<countVertex;i++)
{
for(int j=0;j<countVertex;j++)
{
cout<<adjacency[i][j]<<'\t';//输出弧
}
cout<<endl;
}
}
template <class VertexType, class ArcType, int graph_size>
Error_code Network<VertexType, ArcType, graph_size>::insertVertex(VertexType dataIn)
//插入顶点,数据域为 dataIn
{
if(countVertex==graph_size)
{//如果顶点数量达到上限,则返回错误代码
return overflow;
}
nodes[countVertex]=dataIn;//插入顶点
countVertex++;//顶点数量加1
return success;
}
template <class VertexType, class ArcType, int graph_size>
Error_code Network<VertexType, ArcType, graph_size>::deleteVertex(VertexType dltKey, ArcType infinityArc)
//删除顶点,其数据域中为 dltKey,将该弧变为无穷大的断弧 infinityArc
{
if(countVertex==0)//如果顶点数量为0,则返回错误代码
{
return underflow;
}
int i=0;
if(retrieveVertex(dltKey,i)==fail)//如果没有找到顶点,则返回错误代码
{
return not_present;
}
countArc-=(indegree(dltKey,infinityArc)+outdegree(dltKey,infinityArc));
//删除顶点后,弧数量减去该顶点的入度和出度
for(int j=i;j<countVertex-1;j++)//删除第i行的狐
{
for(int k=0;k<countVertex;k++)
{
adjacency[j][k]=adjacency[j+1][k];
}
}
for(int j=i;j<countVertex-1;j++)//删除第i列的狐
{
for(int k=0;k<countVertex;k++)
{
adjacency[k][j]=adjacency[k][j+1];
}
}
while(i<countVertex-1)//删除顶点
{
nodes[i]=nodes[i+1];
i++;
}
countVertex--;//顶点数量减1
return success;
}
template <class VertexType, class ArcType, int graph_size>
Error_code Network<VertexType, ArcType, graph_size>::insertArc(VertexType fromKey, VertexType toKey,ArcType newInfo, ArcType infinityArc)
//插入弧,起点为 start,终点为 end,权重为 weight
{
if(countArc==graph_size*graph_size)//如果弧数量达到上限,则返回错误代码
{
return overflow;
}
int i,j;
retrieveVertex(fromKey,i);//查找起点
retrieveVertex(toKey,j);//查找终点
if(i==-1||j==-1)//如果没有找到起点或终点,则返回错误代码
{
return not_present;
}
if(adjacency[i][j]!=infinityArc)//如果该弧已存在,则返回错误代码
{
return duplicate_error;
}
adjacency[i][j]=newInfo;//插入弧
countArc++;//弧数量加1
return success;
}
template <class VertexType, class ArcType, int graph_size>
Error_code Network<VertexType, ArcType, graph_size>::deleteArc(VertexType fromKey, VertexType toKey, ArcType infinityArc)
//删除弧,起点为 start,终点为 end
{
if(countArc==0)
{//如果弧数量为0,则返回错误代码
return underflow;
}
int i,j;
retrieveVertex(fromKey,i);
retrieveVertex(toKey,j);
if(i==-1||j==-1)
{//如果没有找到起点或终点,则返回错误代码
return not_present;
}
if(adjacency[i][j]!=infinityArc)//如果该弧不存在,则返回错误代码
{
adjacency[i][j]=infinityArc;//删除弧
countArc--;//弧数量减1
}
return success;
}
template <class VertexType, class ArcType, int graph_size>
Error_code Network<VertexType, ArcType, graph_size>::retrieveVertex(VertexType dataOut, int & i)
//查 DataOut 的顶点,返回该该顶点所在一维数组的位置 i
{
for(int j=0;j<countVertex;j++)
{
if(nodes[j]==dataOut)
{//如果找到顶点,则返回该顶点所在一维数组的位置 i
i=j;
return success;
}
}
i=-1;//如果没有找到顶点,则返回错误代码
return fail;
}
template <class VertexType, class ArcType, int graph_size>
Error_code Network<VertexType, ArcType, graph_size>:: replaceVertex(VertexType dataOld, VertexType dataNew)
//查到 dataOld 的顶点,将其数据改为 dataNew
{
int i;
if(retrieveVertex(dataOld,i)==fail)
{
return not_present;
}
nodes[i]=dataNew;
return success;
}
template <class VertexType, class ArcType, int graph_size>
Error_code Network<VertexType, ArcType, graph_size>::retrieveArc(VertexType fromKey, VertexType toKey, ArcType & dataOut)
//查到 fromKey 到 toKey 的弧,将其权重赋给 dataOut
{
int i,j;
if(retrieveVertex(fromKey,i)==fail||retrieveVertex(toKey,j)==fail)
{
return not_present;
}
dataOut=adjacency[i][j];
return success;
}
template <class VertexType, class ArcType, int graph_size>
Error_code Network<VertexType, ArcType, graph_size>::replaceArc(VertexType fromKey, VertexType toKey, ArcType dataIn,ArcType infinityArc)
//修改弧,该弧从 fromKey 指向 toKey,新弧数据为 dataIn
{
int i,j;
if(retrieveVertex(fromKey,i)==fail||retrieveVertex(toKey,j)==fail)
{
return not_present;
}
if(adjacency[i][j]==infinityArc)
{
countArc++;
}
adjacency[i][j]=dataIn;
return success;
}
template <class VertexType, class ArcType, int graph_size>
VertexType Network<VertexType, ArcType, graph_size>::getVertex(int i)//返回第 i 个顶点的数据域
{
return nodes[i];
}
template <class VertexType, class ArcType, int graph_size>
ArcType Network<VertexType, ArcType, graph_size>::getArc(int i, int j)//返回第 i 个顶点到第 j 个顶点的弧数据域
{
return adjacency[i][j];
}
template <class VertexType, class ArcType, int graph_size>
bool Network<VertexType, ArcType, graph_size>:: empty()//叛图是否为空
{
return countVertex==0;
}
template <class VertexType, class ArcType, int graph_size>
bool Network<VertexType, ArcType, graph_size>:: full()//叛图是否为满
{
return countVertex==graph_size&&countArc==graph_size*graph_size;
}
template <class VertexType, class ArcType, int graph_size>
int Network<VertexType, ArcType, graph_size>:: sizeVertex()//返回顶点数
{
return countVertex;
}
template <class VertexType, class ArcType, int graph_size>
int Network<VertexType, ArcType, graph_size>:: sizeArc()//返回弧数
{
return countArc;
}
template <class VertexType, class ArcType, int graph_size>
int Network<VertexType, ArcType, graph_size>::indegree(VertexType key, ArcType infinityAr) //返回顶点 key 的出度
{
int i;
if(retrieveVertex(key,i)==fail)
{
return 0;
}
int count=0;
for(int j=0;j<countVertex;j++)
{//遍历所有顶点
if(adjacency[i][j]!=infinityAr)
{//如果该顶点有弧指向它,则出度加1
count++;
}
}
return count;
}
template <class VertexType, class ArcType, int graph_size>
int Network<VertexType, ArcType, graph_size>::outdegree(VertexType key, ArcType infinityAr)//返回顶点 key 的入度
{
int i;
if(retrieveVertex(key,i)==fail)
{
return 0;
}
int count=0;
for(int j=0;j<countVertex;j++)
{
if(adjacency[j][i]!=infinityAr)
{//如果该顶点有弧指向它,则入度加1
count++;
}
}
return count;
}
template <class VertexType, class ArcType, int graph_size>
void Network<VertexType, ArcType, graph_size>:: depthFirst(void (*process)(VertexType dataProc), ArcType infinityArc)
//深度优先遍历(需要借助于栈),初始化时可l能需要无穷大的断弧 infinityArc
{
if(countVertex==0)
{//如果叛图为空,则返回
return;
}
stack<int> s;
bool *visited=new bool[countVertex];//记录是否被访问过
for(int i=0;i<countVertex;i++)
{//初始化 visited 数组
visited[i]=false;
}
s.push(0);//入栈第一个顶点
visited[0]=true;//设置第一个顶点为已访问
while(!s.empty())
{
int data=s.top();
s.pop();
process(nodes[data]);//处理顶点数据域
for(int i=countVertex-1;i>=0;i--)
{
if(!visited[i]&&adjacency[data][i]!=infinityArc)
{//如果该顶点未被访问过且有弧指向它,则入栈
s.push(i);
visited[i]=true;
}
}
}
delete [] visited;
}
template <class VertexType, class ArcType, int graph_size>
void Network<VertexType, ArcType, graph_size>:: breadthFirst(void (*process)(VertexType dataProc), ArcType infinityArc)
//广度优先遍历(需要借助于队列),初始化时可能需要无穷大的断弧 infinityArc
{
if (countVertex==0)
{//如果叛图为空,则返回
return;
}
queue<int> q;
bool *visited=new bool[countVertex];//记录是否被访问过
for(int i=0;i<countVertex;i++)
{//初始化 visited 数组
visited[i]=false;
}
q.push(0);//入队第一个顶点
visited[0]=true;//设置第一个顶点为已访问
while(!q.empty())
{
int data=q.front();
q.pop();
process(nodes[data]);//处理顶点数据域
for(int i=0;i<countVertex;i++)
{
if(!visited[i]&&adjacency[data][i]!=infinityArc)
{//如果该顶点未被访问过且有弧指向它,则入队
q.push(i);
visited[i]=true;
}
}
}
delete [] visited;
}
template <class VertexType, class ArcType, int graph_size>
Error_code Network<VertexType, ArcType, graph_size>::shortestPathDistances(VertexType source, ArcType distance[], int prior[], ArcType zeroArc, ArcType infinityArc)
//求单源最短路径,source 为源顶点,distance 数组存储源顶点到所有顶点最短路径距离,
//prior 数组存储最短路径中各顶点的前驱顶点在一维数组的下标。
//zeroArc 为距离 0,infinityArc 为距离无穷大
{
if(countVertex==0)
{//如果叛图为空,则返回
return fail;
}
bool *visited=new bool[countVertex];//记录是否被访问过
for(int i=0;i<countVertex;i++)
{
visited[i]=false;
}
int cnt=0;//source的位置
retrieveVertex(source,cnt);
distance[cnt]=zeroArc;//设置源顶点到自身的距离为0
for(int i=0;i<countVertex;i++)
{
int minIndex=-1;//最短距离的顶点在一维数组的下标
for(int j=0;j<countVertex;j++)
{//找出最短距离的顶点
if(!visited[j]&&(minIndex==-1||distance[j]<distance[minIndex]))
{//如果该顶点未被访问过且距离小于当前最短距离,则设置为最短距离的顶点
minIndex=j;
}
}
if(minIndex==-1)
{//如果没有找到最短距离的顶点,则说明图中没有路径到源顶点
delete [] visited;
return fail;
}
visited[minIndex]=true;//设置最短距离的顶点为已访问
for(int j=0;j<countVertex;j++)
{//更新最短距离
if(!visited[j]&&adjacency[minIndex][j]!=infinityArc)
{
if(distance[minIndex]+adjacency[minIndex][j]<distance[j])
{
distance[j]=distance[minIndex]+adjacency[minIndex][j];//更新距离
prior[j]=minIndex;//设置前驱顶点
}
}
}
}
delete [] visited;
return success;
}
//Dijkstra 优先队列优化版本
// template <class VertexType, class ArcType, int graph_size>
// Error_code Network<VertexType, ArcType, graph_size>::shortestPathDistances(VertexType source, ArcType distance[], int prior[], ArcType zeroArc, ArcType infinityArc)
// //求单源最短路径,source 为源顶点,distance 数组存储源顶点到所有顶点最短路径距离,
// //prior 数组存储最短路径中各顶点的前驱顶点在一维数组的下标。
// //zeroArc 为距离 0,infinityArc 为距离无穷大
// {
// if(countVertex==0)
// {//如果叛图为空,则返回
// return fail;
// }
// bool *visited=new bool[countVertex];//记录是否被访问过
// for(int i=0;i<countVertex;i++)
// {
// visited[i]=false;
// }
// int cnt=0;//source的位置
// retrieveVertex(source,cnt);
// distance[cnt]=zeroArc;//设置源顶点到自身的距离为0
// priority_queue<PII,vector<PII>,greater<PII>> res;//优先队列,存储最短距离的顶点,小顶堆
// res.push({0,cnt});
// while(!res.empty())
// {
// PII top=res.top();
// res.pop();
// int minIndex=top.second;
// if(visited[minIndex])
// {
// continue;
// }
// visited[minIndex]=true;//设置最短距离的顶点为已访问
// for(int j=0;j<countVertex;j++)
// {//更新最短距离
// if(!visited[j]&&adjacency[minIndex][j]!=infinityArc)
// {
// if(distance[minIndex]+adjacency[minIndex][j]<distance[j])
// {
// distance[j]=distance[minIndex]+adjacency[minIndex][j];//更新距离
// prior[j]=minIndex;//设置前驱顶点
// res.push({distance[j],j});//更新优先队列
// }
// }
// }
// }
// delete [] visited;
// return success;
// }
main.cpp
#include"Network.h"
#include"Network.cpp"
const int graph_size=20,zero=0,infinity=999;
void traverse(char a)
{
cout<<a<<'\t';
}
void text1()//测试网络类
{
Network<char,int,graph_size> net(infinity);
net.insertVertex('A');
net.insertVertex('B');
net.insertVertex('C');
net.insertVertex('D');
net.insertVertex('E');
net.insertArc('A','B',1,infinity);
net.insertArc('A','C',1,infinity);
net.insertArc('B','C',1,infinity);
net.insertArc('B','D',1,infinity);
net.insertArc('C','A',1,infinity);
net.insertArc('C','D',1,infinity);
net.insertArc('D','B',1,infinity);
net.insertArc('D','E',1,infinity);
net.insertArc('E','D',1,infinity);
net.insertArc('E','C',1,infinity);
net.insertArc('E','B',1,infinity);
net.write();
cout<<endl;
net.deleteVertex('E',infinity);
cout<<"删除顶点E后:"<<endl;
net.write();
cout<<endl;
net.deleteArc('B','C',infinity);
cout<<"删除弧(B,C)后:"<<endl;
net.write();
cout<<endl;
int res;
net.retrieveVertex('B',res);
cout<<"查找顶点B的位置为:"<<res+1<<endl;
net.retrieveArc('B','C',res);
cout<<"查找弧(B,C)的权值为:"<<res<<endl;
net.replaceArc('B','C', 2 ,infinity);
cout<<"更改弧(B,C)的权值为:2"<<endl;
net.replaceVertex('D','E');
cout<<"替换顶点D为E后:"<<endl;
net.write();
if(net.empty())
{
cout<<"网络为空"<<endl;
}
else
{
cout<<"网络不为空"<<endl;
}
if(net.full())
{
cout<<"网络已满"<<endl;
}
else
{
cout<<"网络未满"<<endl;
}
cout<<"网络中顶点的个数为:"<<net.sizeVertex()<<endl;
cout<<"网络中弧的个数为:"<<net.sizeArc()<<endl;
cout<<"深度优先遍历:"<<endl;
net.depthFirst(traverse,infinity);
cout<<endl;
cout<<"广度优先遍历:"<<endl;
net.breadthFirst(traverse,infinity);
cout<<endl;
}
void text2()//测试求单源最短路径
{
Network<char,int,graph_size> net(infinity);
net.insertVertex('A');
net.insertVertex('B');
net.insertVertex('C');
net.insertVertex('D');
net.insertVertex('E');
net.insertArc('A','B',1,infinity);
net.insertArc('A','C',1,infinity);
net.insertArc('B','C',1,infinity);
net.insertArc('B','D',1,infinity);
net.insertArc('C','A',1,infinity);
net.insertArc('C','D',1,infinity);
net.insertArc('D','B',1,infinity);
net.insertArc('D','E',1,infinity);
net.insertArc('E','D',1,infinity);
net.insertArc('E','C',1,infinity);
net.insertArc('E','B',1,infinity);
net.write();
int *distance=new int[graph_size],*prior=new int[graph_size];
for(int i=0;i<graph_size;i++)
{
distance[i]=infinity;
prior[i]=i;
}
net.shortestPathDistances('A',distance,prior,zero,infinity);
cout<<"A到其他顶点的最短路径为:"<<endl;
for(int i=0;i<net.sizeVertex();i++)
{
cout<<"A到"<<char(i+'A')<<"的最短路径为:"<<distance[i]<<endl;
}
cout<<"A到其他顶点的最短路径的前驱顶点为:"<<endl;
for(int i=0;i<net.sizeVertex();i++)
{
cout<<"A到"<<char(i+'A')<<"的最短路径的前驱顶点为:"<<char(prior[i]+'A')<<endl;
}
delete[] distance;
delete[] prior;
}
struct State//酒瓶的状态
{
int a,b,c;
State(int a=0,int b=0,int c=0)
{
this->a=a;
this->b=b;
this->c=c;
}
bool operator==(const State &s)const
{//重载==运算符
return a==s.a&&b==s.b&&c==s.c;
}
friend ostream& operator<<(ostream &output,const State &s)
{//重载<<运算符
output<<"("<<s.a<<","<<s.b<<","<<s.c<<")";
return output;
}
};
void text3()//平分酒
{
Network<State,int,graph_size> net(infinity);
State start(3,5,0),end(0,4,4);//初始状态和终止状态
int s[]={3,5,8};//酒瓶的最大容量
int sum=8;//酒的总量
for(int i=0;i<=s[0];i++)
for(int j=0;j<=s[1];j++)
if(i+j<=sum)
{
State temp(i,j,sum-i-j);
if((temp.a==0||temp.a==s[0])||(temp.b==0||temp.b==s[1])||(temp.c==0||temp.c==s[2]))
{//至少有一个达到最大值或0
net.insertVertex(temp);//插入状态
}
}
for(int i=0;i<net.sizeVertex();i++)
for(int j=0;j<net.sizeVertex();j++)
{
State x1=net.getVertex(i),x2=net.getVertex(j);
if(i!=j)
{
if(x1.a!=x2.a&&x1.b!=x2.b&&x1.c==x2.c)
{//条件1:只能有2个变量改变
if(x2.a==0||x2.b==0||x2.a==s[0]||x2.b==s[1])
{//条件2:改变的2个变量中至少有一个达到最大值或0
net.insertArc(x1,x2,1,infinity);//满足直接可达,添加有向边1
}
}
else if(x1.a!=x2.a&&x1.c!=x2.c&&x1.b==x2.b)
{
if(x2.a==0||x2.c==0||x2.a==s[0]||x2.c==s[2])
{
net.insertArc(x1,x2,1,infinity);
}
}
else if(x1.b!=x2.b&&x1.c!=x2.c&&x1.a==x2.a)
{
if(x2.b==0||x2.c==0||x2.b==s[1]||x2.c==s[2])
{
net.insertArc(x1,x2,1,infinity);
}
}
}
}
net.write();
int *distance=new int[graph_size],*prior=new int[graph_size];
for(int i=0;i<graph_size;i++)
{
distance[i]=infinity;
prior[i]=i;
}
net.shortestPathDistances(start,distance,prior,zero,infinity);
int cnt1,cnt2;//开始和结束在net的位置
net.retrieveVertex(start,cnt1);
net.retrieveVertex(end,cnt2);
cout<<"最短路径的长度为:"<<distance[cnt2]<<endl;
cout<<"从"<<start<<"到"<<end<<"的最短路径为:"<<endl;
stack<State> path;//路径栈
path.push(end);
while(prior[cnt2]!=cnt1)
{//查找路径
path.push(net.getVertex(prior[cnt2]));
cnt2=prior[cnt2];
}
path.push(start);
while(!path.empty())
{//输出路径
if(path.size()!=1)cout<<path.top()<<"->";
else cout<<path.top()<<endl;
path.pop();
}
delete[] distance;
delete[] prior;
}
int main()
{
text1();//测试网络类
//text2();//测试最短路径算法
//text3();//测试平分酒
system("pause");
return 0;
}