P2269 高质量的数据传输
题目分析:
本题是在最短路的基础上多维护了一个路径,我们正常去做最短路。
做法:
用 spfa 去跑最短路,由于需要维护最少丢失率,我们可以维护最大剩余率,最后用
切记:丢失率可能是
spfa:当一个点的最优值被更新时,那么需要更新与它相连的点。如果需要去更新的点已在队列里不必再入队。
Code
#include<bits/stdc++.h>
using namespace std;
const int N=310;
const double eps=1e-6;
int n,l,r,t[N][N],head[N],tot;
double loss[N][N];
struct node
{
int next,to,dis2;
double dis1;//dis1[]剩余率,dis2[]延时
}edge[N*N];
void read(int from,int to,double dis1,int dis2)
{
tot++;
edge[tot].to=to;
edge[tot].dis1=dis1;
edge[tot].dis2=dis2;
edge[tot].next=head[from];
head[from]=tot;
}
void spfa()
{
double ans1[N]={0};//剩余率
int ans2[N]={0},v[N]={0};//ans2[]延时,v[]标记是否在队列里
ans1[l]=1,v[l]=1;
queue<int>q;
q.push(l);
while(q.size())
{
int x=q.front();
q.pop();
v[x]=0;
for(int i=head[x];i;i=edge[i].next)
{
int y=edge[i].to;
if(ans1[x]*edge[i].dis1>ans1[y])
{
ans1[y]=ans1[x]*edge[i].dis1;
ans2[y]=ans2[x]+edge[i].dis2;
if(v[y]==0)q.push(y),v[y]=1; //如果已经在队列里不必再次入队
}
}
}
printf("%d %.4lf",ans2[r],1-ans1[r]);
}
int main(){
scanf("%d%d%d",&n,&l,&r);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
scanf("%d",&t[i][j]);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
scanf("%lf",&loss[i][j]);
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++)
if(t[i][j]!=-1&&loss[i][j]!=-1)
read(i,j,1-loss[i][j],t[i][j]),read(j,i,1-loss[i][j],t[i][j]);
spfa();
return 0;
}