bzoj2878: [Noi2012]迷失游乐园 基环树dp求路径期望

时间:2022-11-25 22:00:35
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
#define N 110000
int e[N],ne[N*2],v[N*2],w[N*2];
typedef double dd;
int nn;
dd dp1[N];
void add(int x,int y,int z){
    ne[++nn]=e[x],e[x]=nn,v[nn]=y,w[nn]=z;
}
int n,m;
int fa[N];
int du[N];
void dfs1(int x){
    for(int i=e[x];i;i=ne[i]){
        if(fa[x]==v[i])continue;
        fa[v[i]]=x;
        dfs1(v[i]);
        dp1[x]+=dp1[v[i]]+w[i];
    }
    if(x==1)dp1[x]/=du[x];
    else if(du[x]!=1)dp1[x]/=(du[x]-1);
}
void dfs2(int x){
   for(int i=e[x];i;i=ne[i]){
           if(fa[x]==v[i])continue;
       if(du[x]!=1)dp1[v[i]]=(dp1[v[i]]*(du[v[i]]-1)+w[i]+(dp1[x]*du[x]-dp1[v[i]]-w[i])/(du[x]-1))/du[v[i]];
       else dp1[v[i]]=(dp1[v[i]]*(du[v[i]]-1)+w[i])/du[v[i]];
          dfs2(v[i]);
    }    
}
void solv1(){
    dfs1(1);
    dfs2(1);
    dd ans=0;
    for(int i=1;i<=n;i++)ans+=dp1[i];
    printf("%.3lf",ans/n);
}
int been[N];
int bb[N],bn;
int fa2[N];
int rank[N],tot;
void dfs3(int x){
    been[x]=1;
    rank[x]=++tot;
    for(int i=e[x];i;i=ne[i]){
        if(fa[x]==v[i])continue;
        if(been[v[i]]){
            if(rank[v[i]]<rank[x])continue;
            for(int j=v[i];j!=x;j=fa[j]) bb[bn++]=j;
            bb[bn++]=x;
        }else{
            fa[v[i]]=x;
            dfs3(v[i]);
        }    
    }
}
dd ans;
int been2[N];

int rt;
int yy;
dd dfs4(int x,int ff){
//    cout<<"dfs"<<x<<" "<<ff<<endl;
//    if(++yy>15)while(1);
    dd u=0;
    int op=0;
    for(int i=e[x];i;i=ne[i]){
           if(ff==v[i]||v[i]==rt)continue;
           op++;
        u+=dfs4(v[i],x)+w[i];
    }    
    if(op)u/=op;
    return u;
}
void dfs5(int x,int ff){
    int op=0;
    for(int i=e[x];i;i=ne[i]){
        if(v[i]==ff)continue;
        dfs5(v[i],x);
        op++;
        dp1[x]+=dp1[v[i]]+w[i];
    }    
    if(op)dp1[x]/=op;
}
dd dfs6(int x,int ff){
    for(int i=e[x];i;i=ne[i]){
           if(ff==v[i]||been2[v[i]])continue;
       if(du[x]!=1)dp1[v[i]]=(dp1[v[i]]*(du[v[i]]-1)+w[i]+(dp1[x]*du[x]-dp1[v[i]]-w[i])/(du[x]-1))/du[v[i]];
       else dp1[v[i]]=(dp1[v[i]]*(du[v[i]]-1)+w[i])/du[v[i]];
          dfs6(v[i],x);
    }    
}
void solv2(){
    dfs3(1);
    for(int i=0;i<bn;i++){
        rt=bb[i];
        been2[bb[i]]=1;
        dp1[bb[i]]=dfs4(bb[i],0);    
    }
    for(int i=0;i<bn;i++){
       for(int j=e[bb[i]];j;j=ne[j]){
            if(been2[v[j]])continue;
            dfs5(v[j],bb[i]);    
        }    
        dfs6(bb[i],0);
    }
    for(int i=1;i<=n;i++)ans+=dp1[i];
    printf("%.3lf",ans/n);
}
int main(){

    scanf("%d%d",&n,&m);
   for(int i=1;i<=m;i++){
       int a,b,c;
       scanf("%d%d%d",&a,&b,&c);
       add(a,b,c);
       add(b,a,c);           
       du[a]++;
       du[b]++;
   }    
    if(n==m+1)solv1();
    else solv2();
}