题目描述:
Alpha 机构有自己的一套网络系统进行信息传送。情报员 A 位于节点 1,他准备将一份情报 发送给位于节点 n 的情报部门。可是由于最近国际纷争,战事不断,很多信道都有可能被遭到监 视或破坏。 经过测试分析,Alpha 情报系统获得了网络中每段信道安全可靠性的概率,情报员 A 决定选 择一条安全性最高,即概率最大的信道路径进行发送情报。 你能帮情报员 A 找到这条信道路径吗?
输入描述:
第一行: T 表示以下有 T 组测试数据 ( 1≤T ≤8 ) 对每组测试数据: 第一行:n m 分别表示网络中的节点数和信道数 (1<=n<=10000,1<=m<=50000) 接下来有 m 行, 每行包含三个整数 i,j,p,表示节点 i 与节点 j 之间有一条信道,其信 道安全可靠性的概率为 p%。 ( 1<=i, j<=n 1<=p<=100)
输出描述:
每组测试数据,输出占一行,一个实数 即情报传送到达节点 n 的最高概率,精确到小数点后 6 位。
样例输入:
复制
1 5 7 5 2 100 3 5 80 2 3 70 2 1 50 3 4 90 4 1 85 3 1 70
样例输出:
61.200000
这是一道比较简单的求单源最短路径 的问题,但题目存在两个易错点
1.int 无论转化为float还是double类型都会有误差,但转化为double类型误差会小一点题目最终结果让保留六位小数这个就比较坑了,转化为float会出现最后几位出现误差错误
2.题目内存要求为64M,如果用double类型存储数组【10010】【10010】所需内存为80多兆,会超内存,所以只能用邻接表来存储图
代码主要思想使用Dijkstra算法
#include<iostream>
#include<cstring>
#include<vector>
#include<cstdio>
using namespace std;
struct Vertex
{
double edge;
int end;
};//存储到达顶点和边
vector<Vertex> Graph[10010];//图
int visite[10010];//判断是否访问
double dist[10010];//存储最小路径
int n;
int find_max_dist()//寻找dist值最大的dist
{
double max_dist=0.0;
int max_number;
for(int i=1;i<=n;i++)
{
if(visite[i]==0&&dist[i]>max_dist)
{
max_dist=dist[i];
max_number=i;
}
}
if(max_dist>0)
return max_number;
else
return -1;
}
int main()
{
int t;
cin>>t;
while(t--)
{
memset(visite,0,sizeof(visite));
int m;
cin>>n>>m;
int i,j;
for(i=0;i<m;i++)//读入邻接矩阵
{
int a,b,c;
cin>>a>>b>>c;
Vertex v;
v.edge=(double)c/100;
v.end=b;
Graph[a].push_back(v);
v.end=a;
Graph[b].push_back(v);
}
memset(dist,0,sizeof(dist));
for(i=0;i<Graph[1].size();i++)
dist[Graph[1][i].end]=Graph[1][i].edge;
dist[1]=0.00;
visite[1]=1;//初始化
while(1)
{
int k=find_max_dist();
if(k==-1)
break;
visite[k]=1;
for(i=0;i<Graph[k].size();i++)
{
if(visite[Graph[k][i].end]==0&&dist[k]*Graph[k][i].edge>dist[Graph[k][i].end])
dist[Graph[k][i].end]=dist[k]*Graph[k][i].edge;
}
}
printf("%.6f\n",dist[n]*100);
for(i=1;i<=n;i++)//清空邻接矩阵
Graph[i].erase(Graph[i].begin(),Graph[i].end());
}
return 0;
}