Sending Packets LightOJ - 1321
有 n n n 个路由器,编号为 0 ∼ n − 1 0\sim n-1 0∼n−1 ,路由器之间有无向边 u i , v i u_i,v_i ui,vi ,每条边成功传输数据的概率是 p i p_i pi,从 0 0 0 传数据给 n − 1 n-1 n−1,每次传送 1KB,总共 s KB,成功的概率为链路上所有边的 p i p_i pi 的乘积, 0 0 0 处在等待时间 2 K 2K 2K 之后假如收到了确认信号(确认信号不会丢失),那就发送下一 KB,否则重新发送当前 KB,求发送完所有数据的期望时间。
首先用最短路径算法求出一次通过的最大概率 p p p,设成功发送 1 KB 所需要的期望时间是 E E E,则:
E = 2 k ⋅ p + ( 1 − p ) ( 2 k + E ) E = 2 k p \begin{aligned} E&=2k\cdot p+(1-p)(2k+E)\\ E&=\frac{2k}{p} \end{aligned} EE=2k⋅p+(1−p)(2k+E)=p2k
则传送 s KB 需要的时间就是 s E sE sE
代码如下:
#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
//#define WINE
#define MAXN 105
#define MAXM 20005
using namespace std;
int T,iCase,n,m,s,k,u,v,head[MAXN],cnt;
double p,dis[MAXN];bool vis[MAXN];
struct Edge{
int to,nxt;
double p;
}edge[MAXM];
void addedge(int u,int v,double p){
edge[cnt].to=v;
edge[cnt].p=p;
edge[cnt].nxt=head[u];
head[u]=cnt++;
}
struct Node{
int v;double p;
Node(){}
Node(int _v,double _p):v(_v),p(_p){}
bool operator<(const Node&b)const{
return p<b.p;
}
};
void dijkstra(){
priority_queue<Node> q;
memset(vis,false,sizeof(vis));
memset(dis,0,sizeof(dis));
q.push(Node(0,1));
dis[0]=1;
while(!q.empty()){
Node t=q.top();q.pop();
int u=t.v;double p=t.p;
if(vis[u])continue;vis[u]=true;
for(int i=head[u];i!=-1;i=edge[i].nxt){
int v=edge[i].to;double w=edge[i].p;
if(p*w>dis[v]){
dis[v]=p*w;
q.push(Node(v,dis[v]));
}
}
}
}
int main(){
#ifdef WINE
freopen("data.in","r",stdin);
#endif
scanf("%d",&T);
while(T--){
memset(head,-1,sizeof(head));cnt=0;
scanf("%d%d%d%d",&n,&m,&s,&k);
for(int i=0;i<m;i++){
scanf("%d%d%lf",&u,&v,&p);p/=100;
addedge(u,v,p);addedge(v,u,p);
}
dijkstra();
printf("Case %d: %.8lf\n",++iCase,2*k/dis[n-1]*s);
}
return 0;
}