BZOJ 2827 NOI 2012 迷失游乐园 pascal

来源:互联网 发布:学做饭的软件 编辑:程序博客网 时间:2024/04/29 21:18

这一题的树形结构很好做

先随便找一个根,然后计算出 每个点往下走的期望长度

再考虑它往上走的期望即可

down[i]:=sigama(down[x]+a[x,i]|x为i的孩子)/孩子数 a[x,i]为 X和i的长度

up[i]:=(down[i]*(i的孩子数)+(up[fa[i]]*(fa[i]的度)-down[i]-a[fa[i],i])/(i的度数)


这样最后算一下up的平均值就行了


再考虑有环的情况

这个图肯定是一个环 带一些树

每棵树的down按照上面的方法计算

在算up之前 用环上的节点个数平方的复杂度计算一下环上各个点的up

然后再像上面一样计算每个点的up即可


code:


var  last,index,h,tot,n,m,i,x,y,p:longint;  tmp,sum,z:double;  w,s,q,fa,next,a,b,d:array[0..200000] of longint;  down,up,c:array[0..200000] of double;  v:array[0..200000] of boolean;  map:array[0..100,0..100] of double;function dfs(k:longint):boolean;  var    p,y:longint;  begin    h:=h+1;q[h]:=k;    p:=b[k];v[k]:=false;    while p<>0 do      begin        y:=a[p];        if y=q[h-1] then          begin            p:=next[p];            continue;          end;        if v[y]=false then           begin            while k<>y do              begin                index:=index+1;                s[index]:=k;                w[k]:=index;                h:=h-1;                k:=q[h];              end;            index:=index+1;            s[index]:=k;            exit(true);          end;        if dfs(y) then exit(true);        p:=next[p];      end;    v[k]:=true;h:=h-1;exit(false);  end;procedure build(x:longint);  var    t,y,p:longint;    tmp:double;  begin    t:=d[x];p:=b[x];    while p<>0 do      begin        y:=a[p];        if (y=fa[x]) or (v[y]=false) then           begin            p:=next[p];            continue;          end;        fa[y]:=x;        build(y);        if fa[x]=0 then           if v[x] then tmp:=(down[y]+c[p])/t                    else                     if t>2 then tmp:=(down[y]+c[p])/(t-2)                            else tmp:=(down[y]+c[p])         else           if t>1 then tmp:=(down[y]+c[p])/(t-1) else tmp:=(down[y]+c[p]);        down[x]:=down[x]+tmp;        p:=next[p];      end;  end;procedure work(x:longint);  var    t1,t2,p:longint;    tmp:double;  begin    t1:=d[x];t2:=d[fa[x]];    up[x]:=down[x];    if fa[x]<>0 then       begin        p:=b[x];        while (a[p]<>fa[x]) and (p<>0) do          p:=next[p];        if t2>1 then tmp:=(up[fa[x]]*t2-down[x]-c[p])/(t2-1)+c[p] else tmp:=c[p];        up[x]:=(up[x]*(t1-1)+tmp)/t1;      end;    p:=b[x];    while p<>0 do      begin        if (a[p]<>fa[x]) and (v[a[p]]=true) then work(a[p]);        p:=next[p];      end;  end;    begin  read(n,m);  tot:=0;  fillchar(b,sizeof(b),0);  fillchar(d,sizeof(d),0);  fillchar(next,sizeof(next),0);  for i:=1 to m do    begin      read(x,y,z);      tot:=tot+1;a[tot]:=y;c[tot]:=z;next[tot]:=b[x];b[x]:=tot;d[x]:=d[x]+1;      tot:=tot+1;a[tot]:=x;c[tot]:=z;next[tot]:=b[y];b[y]:=tot;d[y]:=d[y]+1;    end;  if (m+1)=n then    begin      fillchar(v,sizeof(v),true);      build(1);      work(1);      sum:=0;      for i:=1 to n do        sum:=sum+up[i];      writeln(sum/n:0:5);    end  else    begin      fillchar(v,sizeof(v),true);      fillchar(w,sizeof(w),0);      h:=0;      dfs(1);      fillchar(v,sizeof(v),true);      for i:=1 to index do        v[s[i]]:=false;      for i:=1 to index do        begin          fa[s[i]]:=0;          build(s[i]);        end;      for i:=1 to index do        begin          p:=b[s[i]];          while p<>0 do            begin              y:=a[p];              if v[y]=false then                begin                  map[w[y],i]:=c[p];                  map[i,w[y]]:=c[p];                end;              p:=next[p];            end;        end;      for i:=1 to index do        begin          h:=i+1;z:=1/d[s[i]];sum:=0;tmp:=0;if h>index then h:=1;          up[s[i]]:=down[s[i]]*(d[s[i]]-2)/(d[s[i]]);last:=i;          while h<>i do            begin               sum:=sum+1;tmp:=tmp+map[last,h];              if sum=(index-1) then up[s[i]]:=up[s[i]]+(down[s[h]]+tmp)*z              else up[s[i]]:=up[s[i]]+(down[s[h]]+tmp)*z*(d[s[h]]-2)/(d[s[h]]-1);              z:=z/(d[s[h]]-1);last:=h;h:=h+1;              if h>index then h:=1;            end;                             h:=i-1;z:=1/d[s[i]];sum:=0;tmp:=0;if h<1 then h:=index;          last:=i;          while h<>i do            begin               sum:=sum+1;tmp:=tmp+map[last,h];              if sum=(index-1) then up[s[i]]:=up[s[i]]+(down[s[h]]+tmp)*z              else up[s[i]]:=up[s[i]]+(down[s[h]]+tmp)*z*(d[s[h]]-2)/(d[s[h]]-1);              z:=z/(d[s[h]]-1);last:=h;h:=h-1;              if h<1 then h:=index;            end;                            end;      for i:=1 to index do        begin          down[s[i]]:=up[s[i]];          work(s[i]);        end;      sum:=0;      for i:=1 to n do        begin          sum:=sum+up[i];        end;      writeln(sum/n:0:5);    end;end.


原创粉丝点击