bzoj2878: [Noi2012]迷失游乐园 基环树dp求路径期望
#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(); }