求两点之间最大噪声值最小值 实验
1.1 实验内容
输入一个具有n个顶点和m条边(n≤100,m≤1000)的无向网,边上的权表示该路段的噪声值。当噪声太大时,耳膜会受到伤害,所以当从某点去往另一点时,总希望路上经过的噪声最大值最小。输入一些询问,每次询问输入2个点,输出这两个点之间最大噪声值最小的值。
输入文件中第一行有3个整数:n、m和k。n表示图中的顶点数(在无向图中,我们将所有结点从1到n进行编号),m表示图中的边数,k表示询问次数;接下来m行。每行用3个整数a、b、c描述一条连接结点a和b的边,以及ab路段上的噪声值c;再接下来k行,每行用两个整数a和b表示要询问的两个顶点。
1.2文件结构、开发环境等说明
文件名 | 文件类型 | 功能简介 | 备注 |
Assistance.h | 头文件 | 辅助软件包 | |
AdjListDirNetwork.h | 头文件 | 邻接表类模板头文件,包括数据成员及成员函数的声明与定义 | |
AdjListDirNetworkArc.h | 头文件 | 邻接表边结点类模板头文件,包括数据成员及成员函数的声明与定义 | |
AdjListDirNetworkVec.h | 头文件 | 邻接表顶点结点类模板头文件,包括数据成员及成员函数的声明与定义 | |
ShortestPathFloyd.h | 头文件 | Floyd算法与显示最大噪声值最小路径上的最大噪声值的两个函数的定义 | |
test.cpp | 源文件 | 测试文件 |
1.3 实现技术
1、文件输入
在含有头文件、源程序文件的文件夹中新建input.in IN文件,按照题干输入数据的要求将数据输入。在main()函数中调用文件输入输出库中的open()函数打开输入文件,借助if条件语句来判断文件是否打开。若打开,则将第一行的3个整数输入到整数变量n、m、k中。
ifstream f;
f.open("input.in");
if(f.is_open())
{
f >> n >> m >> k;
……
}
2、噪声值及路径输入
如果顶点数、边数、询问次数都为0,则return,不进行接下来的操作。否则,利用双重for循环,将二维数组g中的所有值都设为infity,后通过for循环输入两点以及两点之间的权值,并将权值(噪声值)赋值给g[a-1][b-1]、g[b-1][a-1],此时如果g[i][j]的值为infity,表示i和j之间没有直接的通路。
if (n == 0 && m == 0 && k == 0) return 0;
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
g[i][j] = infity;
for (int i = 0; i < m; i++)
{
int a, b, c; f >> a >> b >> c;
g[a-1][b-1] = g[b-1][a-1] = c;
}
3、用邻接表表示该无向网
用邻接表作为存储结构,表示题目所给无向图。
AdjListDirNetwork<char, int> net(vexs, n);
for (int u = 0; u < n; u++)
for (int v = n - 1; v >= 0; v--)
if (g[u][v] != infity) net.InsertArc(u, v, g[u][v]);
cout << "原网:" << endl;
net.Display(); // 显示网net
cout << endl;
system("PAUSE"); // 调用库函数system()AdjListDirNetwork<char, int> net(vexs, n);
for (int u = 0; u < n; u++)
for (int v = n - 1; v >= 0; v--)
if (g[u][v] != infity) net.InsertArc(u, v, g[u][v]);
cout << "原网:" << endl;
net.Display(); // 显示网net
cout << endl;
system("PAUSE"); // 调用库函数system()
4、用Floyd算法求最短路径
在main()中定义dist二维数组,并分配存储空间。
int** dist;
// 分配存储空间
dist = new int* [net.GetVexNum()];
for (int i = 0; i < net.GetVexNum(); i++) {
dist[i] = new int[net.GetVexNum()];}
调用在头文件ShortestPathFloyd.h中的ShortestPathFloyd()函数。用Floyd算法求有向网中给定顶点之间最大噪声值最小路径上的最大噪声值。先将dist[u][v]都设为-1,再用双重循环把图中有权值的边的值赋给dist[u][v],此时如果dist[u][v]等于-1,则说明顶点u和v之间没有直接通路。再通过三重循环,依次加入其他顶点作为中间顶点,如果增加中间顶点后,得到的路径上最大噪声值比原来的小,则以次新的最大噪声值代替原最大噪声值。如果增加中间顶点后,得到的路径上最大噪声值比原来的大,则dist[u][v]保持原值不变。值得一提的是,在循环体中先通过if判断加入后的顶点与原先的u、v顶点之间是否有通路,若没有则通过continue不需要进行此次循环。至此,就通过Floyd算法的思想得到了每两个顶点之间最大噪声值最小的值,如果dist[u][v]=-1,说明不存在通路。
template <class ElemType, class WeightType>
void ShortestPathFloyd(const AdjListDirNetwork<ElemType, WeightType>& g,WeightType** dist)
{
for (int u = 0; u < g.GetVexNum(); u++)
for (int v = 0; v < g.GetVexNum(); v++)
dist[u][v] = -1;
for (int u = 0; u < g.GetVexNum(); u++)
for (int v = 0; v < g.GetVexNum(); v++)
if (u != v && g.GetWeight(u, v) != g.GetInfinity())
dist[u][v] = g.GetWeight(u, v);
for (int k = 0; k < g.GetVexNum(); k++)
for (int i = 0; i < g.GetVexNum(); i++)
for (int j = 0; j < g.GetVexNum(); j++)
{
if (dist[i][k] == -1 || dist[k][j] == -1) continue;
if (dist[i][j] == -1)//未通路
dist[i][j] = dist[j][i] = max(dist[i][k], dist[k][j]); //两点还未通路,则直接取该路径噪声最大值。
else
{
if (dist[i][j] < max(dist[i][k], dist[k][j]))
dist[i][j] = dist[j][i];
else
dist[i][j] = dist[j][i] = max(dist[i][k], dist[k][j]);
}
}
}
5、文件输入要询问的顶点信息
从输入文件中读取要询问的顶点信息,并根据询问次数来多次调用显示最大噪声值中最小的值的函数DisplayPathAndDist()。
for (int i = 0; i < k; i++)
{
f >> a1 >> b1;
DisplayPathAndDist(net, dist, a1, b1);// 显示最大噪声值
cout << endl;
}
6、显示最小的最大噪声值的函数
根据文件读入要询问的顶点信息:a1、b1,调用邻接表中的GetElem()函数取顶点为v1的元素值到e1中,取顶点为v2的元素值到e2中。如果存在从v1到v2路径,则输出从顶点a1到b1的路径中最小的最大噪音值dist[a1-1][b1-1],若无路径,则输出“dist = ∞”。
template <class ElemType, class WeightType>
void DisplayPathAndDist(const AdjListDirNetwork<ElemType, WeightType>& g,WeightType** dist,int a1,int b1)
{
ElemType e1, e2, e3;
g.GetElem(a1-1, e1); //取顶点为v1的元素值到e1中
g.GetElem(b1-1, e2);//取顶点为v2的元素值到e2中
if (dist[a1-1][b1-1] > -1) { // 存在从v1到v2路径
cout << "从 " << e1 << " 到 " << e2 << ":";
cout << " 所有路径中最小的最大噪音值为 = " << dist[a1-1][b1-1];
}
else { // 从v1到v2无路径
cout << "from " << e1 << " to " << e2 << ":";
cout << " dist = ∞";
}
}
1.4测试结果
1、测试实例
2、邻接表表示无向网
3、询问的两个顶点之间所有路径中最小的最大噪声值
根据Floyd算法手动推导出来的值一致:
完整代码可看资源区
创作不易~麻烦点个赞~~谢谢大家~~~