题解:P2269 [HNOI2002] 高质量的数据传输

Idea

看见 n200n\le200,果断采用 Floyd。

在 Floyd 的过程中,我们维护两个数值:从 iijj 的最小丢包率,从 iijj 的延时(注意不一定是最短的)。

题目要求丢包率优先,我们直接模拟即可。注意到在丢包率小的情况下延时不一定最小,所以延时不可以取最小值。

接下来我们解决丢包率更新的问题。我们设现在枚举到了 i,j,ki,j,k(其中 kk 为途经点),并且 iikkjjkk 之间均有连边,我们设 iijj 之间最小的丢包率为 disi,jdis_{i,j},则有经过 kkiijj 的最小丢包率 dis=1(1disj,k)×(1disi,k)dis=1-(1-dis_{j,k})\times (1-dis_{i,k})

根据定义,我们不难发现:若使经过 kkiijj 的最小丢包率最小,必须使得 (1pi)\prod(1-p_i) 最大,其中 pip_i 为使得经过 kkiijj 的丢包率最小所经过的一条边的丢包率。

不难发现如果保证 disi,kdis_{i,k} 最小,disj,kdis_{j,k} 最小,则 1disi,k1-dis_{i,k}1disj,k1-dis_{j,k} 一定最大。它们相乘的结果根据定义其实就是 (1pi)\prod(1-p_i),用 11 减去它就是更新的答案。当然这个答案不一定最小。

Code

#include<bits/stdc++.h>
using namespace std;
double dis2[205][205],b[205][205];
long long dis1[205][205],a[205][205];
int n,s,t;
int main(){
	cin>>n>>s>>t;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			cin>>dis1[i][j];
		}
	}
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			cin>>dis2[i][j];
		}
	}
	for(int k=1;k<=n;k++){
		for(int i=1;i<=n;i++){
			for(int j=1;j<=n;j++){
				if(dis1[i][k]==-1||dis1[j][k]==-1)continue;
				double nans=1-(1-dis2[i][k])*(1-dis2[j][k]);
				if(nans<dis2[i][j]){
					dis2[i][j]=nans;
					dis1[i][j]=dis1[i][k]+dis1[j][k];
				}
				else if(nans==dis2[i][j]&&dis1[i][j]>dis1[i][k]+dis1[j][k]){
					dis1[i][j]=dis1[i][k]+dis1[j][k];
				}
			}
		}
	}
	printf("%lld %.4lf",dis1[s][t],dis2[s][t]);
	return 0;
}
posted @   Weslie_qwq  阅读(3)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示