BZOJ 2878 迷失游乐园

http://www.lydsy.com/JudgeOnline/problem.php?id=2878

题意:n个点的图,保证图联通,有n-1或者n条边,求从任意一个点出发,不经过相同点,最终无路可走的路径长度期望。

思路:m=n-1时,可以用dp,处理出i点往下,i点往上走的路径长度期望,然后O(n)统计就可以了。

m=n时,由于环上点点数不超过20,那这就是基环树,我们考虑枚举基环树上面的点i,假设我们到了i,并走向了i的子树。

这样我们就把环断开了,然后我们再两遍顺逆走这个环,就可以处理出up数组了,然后再分别下传到每个子树里。

  1 #include<algorithm>
  2 #include<cstdio>
  3 #include<cmath>
  4 #include<cstring>
  5 #include<iostream>
  6 int flag,n,m,f[200005],len[200005],vis[200005],tot,go[200005],next[200005],cnt,cir[200005],huan[200005],first[200005],val[200005],du[200005];
  7 double down[200005],up[200005];
  8 int read(){
  9     char ch=getchar();int t=0,f=1;
 10     while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
 11     while ('0'<=ch&&ch<='9'){t=t*10+ch-'0';ch=getchar();}
 12     return t*f;
 13 }
 14 void insert(int x,int y,int z){
 15     tot++;
 16     go[tot]=y;
 17     next[tot]=first[x];
 18     first[x]=tot;
 19     val[tot]=z;
 20 }
 21 void add(int x,int y,int z){
 22     insert(x,y,z);insert(y,x,z);
 23 }
 24 void dfs1(int x,int fa){
 25     vis[x]=1;
 26     for (int i=first[x];i;i=next[i]){
 27         int pur=go[i];
 28         if (vis[pur]) continue;
 29         dfs1(pur,x);
 30         down[x]+=(double)val[i]+(((double)down[pur])/((double)(du[pur]-1+(du[pur]==1))));
 31     }
 32 }
 33 void dfs2(int x,int fa){
 34     if (!cir[x]&&fa!=0) up[x]=len[x]+((double)((double)up[fa]+down[fa]-len[x]-((double)down[x])/((double)du[x]-1+(du[x]==1))))/((double)(du[fa]-1+(du[fa]==1)));
 35     vis[x]=1;
 36     for (int i=first[x];i;i=next[i]){
 37         int pur=go[i];
 38         if (vis[pur]) continue;
 39         f[pur]=x;
 40         len[pur]=val[i];
 41         dfs2(pur,x);
 42     }
 43 }
 44 void work1(){
 45     dfs1(1,0);
 46     for (int i=1;i<=n;i++) vis[i]=0;
 47     dfs2(1,0);
 48     double ans=0;
 49     for (int i=1;i<=n;i++) ans+=((double)down[i]+(double)up[i])/((double)du[i]);
 50     ans/=((double)(n));
 51     printf("%.5f
",ans);
 52 }
 53 void dfs(int x,int fa){
 54     vis[x]=1;
 55     for (int i=first[x];i;i=next[i]){
 56         int pur=go[i];
 57         if (flag) return;
 58         if (f[x]!=pur&&vis[pur]){
 59             len[pur]=val[i];
 60             int j=x;
 61             while (j!=f[pur]){
 62                 cnt++;
 63                 cir[j]=1;
 64                 huan[cnt]=j;
 65                 j=f[j];
 66             }
 67             flag=1;
 68             return;
 69         }else if (!vis[pur]){
 70             len[pur]=val[i];
 71             f[pur]=x;
 72             dfs(pur,x);
 73         }
 74     }
 75 }
 76 void work2(){
 77      flag=0;
 78      dfs(1,0);cnt++;    
 79      for (int i=1;i<=n;i++) vis[i]=0;
 80      for (int i=0;i<cnt;i++) vis[huan[i]]=1;
 81      for (int i=0;i<cnt;i++) dfs1(huan[i],0);
 82      for (int i=0;i<cnt;i++){
 83             int x=(i+1)%cnt;double s=1;
 84             while (x!=i){
 85                 if ((x+1)%cnt==i) up[huan[i]]+=(double)s*len[huan[(x-1+cnt)%cnt]]+((double)(s*down[huan[x]]))/((double)(du[huan[x]]-2+(du[huan[x]]==2)));
 86                 else up[huan[i]]+=(double)s*len[huan[(x-1+cnt)%cnt]]+((double)(s*down[huan[x]]))/((double)(du[huan[x]]-1));
 87                 s=s/((double)(du[huan[x]]-1));
 88                 x=(x+1)%cnt;
 89             }
 90             x=(i-1+cnt)%cnt;s=1;
 91             while (x!=i){
 92                 if ((x-1+cnt)%cnt==i) up[huan[i]]+=(double)s*len[huan[x]]+((double)(s*down[huan[x]]))/((double)(du[huan[x]]-2+(du[huan[x]]==2)));
 93                 else up[huan[i]]+=(double)s*len[huan[(x)%cnt]]+((double)(s*down[huan[x]]))/((double)(du[huan[x]]-1));
 94                 s=s/((double)(du[huan[x]]-1));
 95                 x=(x-1+cnt)%cnt;
 96             }
 97     }
 98     for (int i=1;i<=n;i++) vis[i]=0;
 99     for (int i=0;i<cnt;i++) vis[huan[i]]=1;
100     for (int i=0;i<cnt;i++) dfs2(huan[i],0);
101     double ans=0;
102     for (int i=1;i<=n;i++) ans+=(down[i]+up[i])/(du[i]);
103     printf("%.5f
",ans/n);
104 }
105 int main(){
106     cnt=-1;
107     n=read();m=read();flag=0;
108     for (int i=1;i<=m;i++){
109         int x=read(),y=read(),z=read();
110         add(x,y,z);
111         du[x]++;du[y]++;
112     }
113     if (m==n-1) work1();
114     else work2();
115 }
原文地址:https://www.cnblogs.com/qzqzgfy/p/5600846.html