1 条题解

  • 0
    @ 2023-6-21 20:06:45

    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

    #6078. 「2017 山东一轮集训 Day7」重排

    信息

    ID
    1034
    时间
    2000ms
    内存
    512MiB
    难度
    (无)
    标签
    递交数
    0
    已通过
    0
    上传者