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 }
  • 相关阅读:
    HDU2013 蟠桃记
    HDU2012 素数判定
    I00030 Grades conversion
    HDU2011 多项式求和
    HDU2009 求数列的和
    HDU2005 第几天?【日期计算】
    HDU2004 成绩转换
    HDU2006 求奇数的乘积
    HDU2007 平方和与立方和【序列处理】
    HDU2010 水仙花数【进制+趣味程序】
  • 原文地址:https://www.cnblogs.com/HLAUV/p/10358058.html
Copyright © 2011-2022 走看看