信道安全
时间限制:
1000 ms | 内存限制:
65535 KB
难度:
2
-
描述
-
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
-
这个题考的最短路模板,我用的SPFA只用了58Ms,一开始用的迪杰斯特拉,10000*10000的数组直接mle,在下面会附上一段迪杰斯特拉AC的代码,用了边集数组优化,那个是学弟写的,个人认为SPFA确实好用,也推荐有SPFA处理最短路问题,这个题需要注意的是求最长路,而且数组的精度要处理好。
#include<stdio.h> #include<queue> #include<string.h> #define inf 0x3f3f3f3f #define maxn 50005 using namespace std; int n,m,len; struct node { int next,v,u; double w; }ans[maxn*2]; int first[maxn]; double dis[maxn]; int vis[maxn]; void add(int u,int v,int w) //数组模拟链表,next数组存储位置 { ans[len].u=u; ans[len].v=v; ans[len].w=w/100.0; ans[len].next=first[u]; first[u]=len++; } void spfa(int st) { dis[st]=1.0; vis[st]=1; queue<int>q; q.push(st); while(!q.empty()) { st=q.front(); q.pop(); vis[st]=0; for(int i=first[st];i!=-1;i=ans[i].next) { if(dis[ans[i].v]<dis[st]*ans[i].w) { dis[ans[i].v]=dis[st]*ans[i].w; if(!vis[ans[i].v]) { vis[ans[i].v]=1; q.push(ans[i].v); } } } } printf("%lf\n",dis[n]*100); } int main() { //freopen("C:\\input.txt","r",stdin); int t; scanf("%d",&t); while(t--) { memset(dis,0,sizeof(dis)); memset(vis,0,sizeof(vis)); memset(first,-1,sizeof(first)); int x,y,z; scanf("%d%d",&n,&m); int len=1; for(int i=1;i<=m;i++) { scanf("%d%d%d",&x,&y,&z); add(x,y,z); add(y,x,z); } spfa(1); } return 0; }
接下来给迪杰斯特拉的AC代码,用时911ms,刚好卡1s的界限
-
#include <bits/stdc++.h> using namespace std; const int MAXN = 10010; double short_path(list<pair<int, double> > *ls, int n) { double cos[MAXN]; //最高概率 int vis[MAXN]; //访问 memset(cos, 0, sizeof(cos)); memset(vis, 0, sizeof(vis)); for (list<pair<int, double> >::iterator it = ls[1].begin(); it != ls[1].end(); it++) cos[it->first] = it->second; vis[1] = 1; for (int i = 2; i < n; i++) { double _max = -1; int k; for (int j = 1; j < n; j++) if (!vis[j] && _max < cos[j]) { _max = cos[j]; k = j; } vis[k] = 1; for (list<pair<int, double> >::iterator it = ls[k].begin(); it != ls[k].end(); it++) if (!vis[it->first] && _max * it->second > cos[it->first]) cos[it->first] = _max * it->second; } return cos[n]; } int main() { #ifdef LOCAL freopen("C:/input.txt", "r", stdin); #endif int t; cin >> t; for (int ti = 0; ti < t; ti++) { list<pair<int, double> > ls[MAXN]; int n, m; cin >> n >> m; for (int mi = 0; mi < m; mi++) { int i, j, p; cin >> i >> j >> p; ls[i].push_back(pair<int, double>(j, p / 100.0)); ls[j].push_back(pair<int, double>(i, p / 100.0)); } printf("%.6lf\n", short_path(ls, n) * 100.0); } return 0; }