zoukankan      html  css  js  c++  java
  • 【NOI2012】迷失游乐园

    题目链接:迷失游乐园(BZOJ)  迷失游乐园(Luogu)

    独立完成的题,写一发题解纪念一波~


    模拟完样例大概可以知道是道树形DP了。

    观察数据范围,发现是基环树,至少会有一个环。

    先从树的部分开始考虑,如果没有环,怎么DP呢?

    先选取一个点为根,f[i]表示从i节点出发走到其子树的路径期望长度。

    那么f[x]= sum(f[son]+w[i])/(rd[x]-1),w[i]为son到x的边长,rd[x]为x的度数,当然如果到了根节点,就不必要减1。

    然后再换根一波,统计答案就可以了。换根时注意节点度数的处理就行。

    这样就能轻松拿到50分的良心部分分。

    如果是基环树呢?

    习惯把基环树看成一个“细菌”,把环放正中间考虑。

    每一个在环上的点都连接着一个子树,先用前面树形DP的方法对每部分子树进行求解,先不换根。

    对于环上每个点,可以逆时针走,也可以顺时针走,所以枚举它左右两条边断掉,拆成链。

    在链上推一遍就可以得到从这个点往右或往左走的路径期望长。(环上点数量很少,复杂度在允许的范围内)

    用这两种期望长度再去更新这个点,然后跑到这个点对应的子树去换根、统计答案。

    算期望除以点度数时比较繁琐,写的时候要小心。

    代码~

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstdlib>
      4 #include<cstring>
      5 #include<algorithm>
      6 
      7 #define For(i,a,b) for(register int i=a;i<=b;++i)
      8 #define Dwn(i,a,b) for(register int i=a;i>=b;--i)
      9 #define Re register
     10 #define Db double
     11 
     12 using namespace std;
     13 
     14 const int N=1e5+5;
     15 
     16 int head[N],nxt[N*2],v[N*2],cnt=1;
     17 Db f[N],w[N*2],rd[N],z,ans=0,Dn;
     18 int n,x,y,m;
     19 bool Fcr[N],vis[N],Ffd=0;
     20 
     21 inline void read(int &v){
     22     v=0;
     23     char c=getchar();
     24     while(c<'0'||c>'9')c=getchar();
     25     while(c>='0'&&c<='9')v=v*10+c-'0',c=getchar();
     26 }
     27 inline void read(Db &v){
     28     v=0;
     29     char c=getchar();
     30     while(c<'0'||c>'9')c=getchar();
     31     while(c>='0'&&c<='9')v=v*10+c-'0',c=getchar();
     32 }
     33 void add(int ux,int vx,Db wx){
     34     cnt++; rd[ux]+=1;
     35     nxt[cnt]=head[ux]; head[ux]=cnt; v[cnt]=vx; w[cnt]=wx;
     36     cnt++; rd[vx]+=1;
     37     nxt[cnt]=head[vx]; head[vx]=cnt; v[cnt]=ux; w[cnt]=wx;
     38 }
     39 void dfsDP(int x,int fa){
     40     for(Re int i=head[x];i;i=nxt[i]){
     41         int vv=v[i]; if(vv==fa)continue;
     42         if(Fcr[vv])continue;
     43         dfsDP(vv,x);
     44         f[x]+=f[vv]+w[i];
     45     }
     46     if(rd[x]>1&&fa)f[x]/=(rd[x]-1.0);
     47     if(fa==0&&rd[x])f[x]/=rd[x]; 
     48 }
     49 void dfsFA(int x,int fa){
     50     ans+=f[x]/Dn; 
     51     for(Re int i=head[x];i;i=nxt[i]){
     52         int vv=v[i]; if(vv==fa)continue;
     53         if(Fcr[vv])continue;
     54         Db Bfx=f[x]; Db Bfv=f[vv];
     55         
     56         Bfx=f[x]*rd[x]-f[vv]-w[i];
     57         if(rd[x]>1)Bfx/=(rd[x]-1);
     58         
     59         f[vv]=f[vv]*(rd[vv]-1)+Bfx+w[i]; 
     60         f[vv]/=rd[vv];
     61         dfsFA(vv,x);
     62         f[vv]=Bfv;
     63     }
     64 }
     65 int st[N],top=0,tot=-1,cr[N][2];
     66 Db dsf[N],dcr[N][2],fx[N][2];
     67 void dfsCIR(int x,int fa){
     68     vis[x]=1; st[++top]=x; 
     69     for(Re int i=head[x];i;i=nxt[i]){
     70         int vv=v[i]; if(vv==fa)continue;
     71         if(vis[vv]){
     72             Ffd=1;
     73             while(st[top]!=vv){
     74                 int stx=st[top--];
     75                 cr[++tot][0]=stx; dcr[tot][0]=dsf[stx]; Fcr[stx]=1;
     76             }
     77             cr[++tot][0]=vv; dcr[tot][0]=w[i]; Fcr[vv]=1;
     78             return;
     79         }
     80         dsf[vv]=w[i];
     81         dfsCIR(vv,x);
     82         if(Ffd)return;
     83     }
     84     top--;
     85 }
     86 void getF12(int pos,int now){
     87     int p=pos+1;
     88     Db Fx=0;
     89     if(p>tot)p=0; 
     90     Fx=f[cr[p][now]];
     91     do{
     92         Fx+=dcr[p][now];
     93         p++; if(p>tot)p=0;
     94         if(p==pos)break;
     95         int cx=cr[p][now];
     96         Db Fcx=f[cx]*(rd[cx]-2);
     97         Fx=(Fx+Fcx)/(rd[cx]-1);
     98     }while(p!=pos);
     99     fx[ cr[pos][now] ][now]=Fx;
    100 }
    101 
    102 int main(){
    103     read(n); read(m); Dn=n;
    104     memset(Fcr,0,sizeof(Fcr));
    105     memset(vis,0,sizeof(vis));
    106     For(i,1,m){
    107         read(x); read(y); read(z);
    108         add(x,y,z);
    109     }
    110     if(m<n){
    111         dfsDP(1,0); dfsFA(1,0);
    112         printf("%.05lf",ans);
    113         return 0;
    114     }
    115     dfsCIR(1,0); 
    116     For(i,0,tot){
    117         rd[cr[i][0]]-=2;
    118         dfsDP(cr[i][0],0);
    119         rd[cr[i][0]]+=2;
    120     }
    121     For(i,0,tot){
    122         cr[i][1]=cr[tot-i][0];
    123         if(i!=tot)dcr[i][1]=dcr[tot-i-1][0];
    124         else dcr[i][1]=dcr[tot][0];
    125     }
    126  
    127     For(i,0,tot){
    128         getF12(i,0); getF12(i,1);
    129     }
    130     For(i,0,tot){
    131         int cx=cr[i][0];
    132         f[cx]*=(rd[cx]-2);
    133         f[cx]+=fx[cx][0]+fx[cx][1];
    134         f[cx]/=rd[cx];
    135         dfsFA(cx,0);
    136     }
    137     printf("%.05lf",ans);
    138     return 0;
    139 }
  • 相关阅读:
    Java安全之JNDI注入
    Visual Studio 2019 升级16.8之后(升级.Net 5),RazorTagHelper任务意外失败
    .Net Core 3.1升级 .Net 5后出现代码错误 rzc generate exited with code 1.
    重走py 之路 ——普通操作与函数(三)
    重走py 之路 ——字典和集合(二)
    设计模式结(完结篇)
    重走py 之路 ——列表(一)
    RestfulApi 学习笔记——分页和排序(五)
    RestfulApi 学习笔记——查询与过滤还有搜索(五)
    Android开发 Error:The number of method references in a .dex file cannot exceed 64K.Android开发 Error:The number of method references in a .dex file cannot exceed 64K
  • 原文地址:https://www.cnblogs.com/HLAUV/p/10358058.html
Copyright © 2011-2022 走看看