1 条题解
-
0
C++ :
#pragma GCC optimize ("O2") #include<iostream> #include<cstdio> #include<cstring> #include<queue> #include<algorithm> using namespace std; const double eps=1e-11; const int maxn=1010; const double inf=1000000; int n,m,S,T,du[maxn],lst[maxn],cnt,vis[maxn],id[maxn],cnta,cntb,to[maxn],total,Now,flag[maxn]; double len[maxn],sum[maxn*maxn],f[maxn]; struct Node{ double f; int id; }g[maxn*maxn],e[maxn*maxn],d[maxn*maxn]; int dcmp(double x){ if(x<eps&&x>-eps)return 0; return x>0?1:-1; } bool cmp(const int &a,const int &b){ if(a==Now)return 0; else if(b==Now)return 1; return f[a]<f[b]; } bool cmp1(const Node &a,const Node &b){ return a.f<b.f; } struct Edge{ int to,next; double w; }; queue<int>que; #define p edge[i].to struct Graph{ Edge edge[maxn]; int head[maxn],tot; void add(int x,int y,double w){ edge[++tot].to=y; edge[tot].next=head[x]; edge[tot].w=w; head[x]=tot; } void Tupo(){ vis[T]=1; for(int i=1;i<=n;i++)if(!du[i]||i==T)que.push(i); while(!que.empty()){ int x=que.front(); lst[++cnt]=x; que.pop(); for(int i=head[x];i;i=edge[i].next){ du[p]--; if(vis[x])vis[p]=1; if(!du[p])que.push(p); } } } void before(int x){ total=0; Now=x; cnta=0;cntb=0;total=0; for(int i=head[x];i;i=edge[i].next){ len[++total]=edge[i].w; to[total]=edge[i].to; } sort(to+1,to+total+1,cmp); for(int i=1;i<=total;i++) for(int j=1;j<=total;j++){ if(to[j]==x)e[++cntb].f=len[i],e[cntb].id=j; else g[++cnta].f=len[i]+f[to[j]],g[cnta].id=j; } sort(e+1,e+cntb+1,cmp1); sort(g+1,g+cnta+1,cmp1); } double query(int x,double mid){ total=0; for(int i=head[x];i;i=edge[i].next){ e[++total].id=p; e[total].f=p==x?mid:f[p]; len[total]=edge[i].w; } sort(e+1,e+total+1,cmp1); double ans=0; for(int i=1;i<=total;i++) for(int j=1;j<=total;j++){ double P=1; for(int k=1;k<=total;k++){ int Count=0; if(k==j){ P/=k; continue; } for(int k1=1;k1<=total;k1++){ if(k1==i)continue; if((k>j&&dcmp(len[k1]+e[k].f-len[i]-e[j].f)>0)||(k<j&&dcmp(len[k1]+e[k].f-len[i]-e[j].f)>=0)){ Count++; } } P=P*(Count-(k-1-(k>j)))/k; } ans+=P*(len[i]+e[j].f); } return ans; } double solve(int x){ double l=0,r=inf,maxx=0; for(int i=1;i<=64;i++){ double mid=(l+r)/2.0; double t=query(x,mid); if(dcmp(mid-t)<=0)l=mid; else r=mid; } return (l+r)/2.0; } }E,G; double query(int x,double mid){ for(int i=1;i<=cntb;i++)e[i].f+=mid; int c=0,temp1=1,temp2=1; while(temp1<=cnta||temp2<=cntb){ if(temp1>cnta)d[++c]=e[temp2],temp2++; else if(temp2>cntb)d[++c]=g[temp1],temp1++; else{ if(g[temp1].f<e[temp2].f)d[++c]=g[temp1],temp1++; else d[++c]=e[temp2],temp2++; } } int type=0; for(int i=0;i<=total;i++){ if(i!=0)id[i]=i; if(i==total||f[to[i+1]]>mid){ type=i+1; for(int j=i+1;j<=total;j++)if(to[j]==x)id[j]=type++; for(int j=i+1;j<=total;j++){ if(to[j]==x)break; id[j]=type++; } break; } } for(int i=1;i<=total;i++)flag[i]=0; int appe=0; long double now=1.0; sum[c+1]=0; for(int i=c;i>=1;i--){ int t=d[i].id; if(flag[t]+1==id[t]){ flag[t]++; appe++; now/=appe; } else if(flag[t]>=id[t]){ now=now/(flag[t]-id[t]+1)*(flag[t]-id[t]+2); flag[t]++; } else flag[t]++; // if(x==1) cout<<x<<"***"<<mid<<" "<<now<<" "<<appe<<" "<<flag[t]<<endl; if(appe==total)sum[i]=now; else sum[i]=0; } for(int i=1;i<=cntb;i++)e[i].f-=mid; long double ans=0; for(int i=c;i>=1;i--){ ans+=(sum[i]-sum[i+1])*d[i].f; } return ans; } double solve(int x){ if(!cntb){ return query(x,inf); } double l=0,r=inf,maxx=0; for(int i=1;i<=64;i++){ double mid=(l+r)/2.0; double t=query(x,mid); if(dcmp(mid-t)<=0)l=mid; else r=mid; } return (l+r)/2.0; } int main(){ // freopen("tomoya2.in","r",stdin);freopen("tomoya.out","w",stdout); scanf("%d%d%d%d",&n,&m,&S,&T); for(int i=1;i<=m;i++){ int x,y; double w; scanf("%d%d%lf",&x,&y,&w); E.add(x,y,w); G.add(y,x,w); if(x!=y)du[x]++; } G.Tupo(); if(!vis[S]){ printf("-1"); return 0; } for(int i=1;i<=n;i++)f[i]=inf; for(int i=1;i<=cnt;i++){ int x=lst[i]; if(!vis[x])continue; if(x==T){ f[x]=0; continue; } E.before(x); f[x]=solve(x); } printf("%.6lf",f[S]); return 0; }
- 1
信息
- ID
- 1034
- 时间
- 2000ms
- 内存
- 512MiB
- 难度
- (无)
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者