题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2878

这个博客写得很好:https://www.cnblogs.com/qt666/p/7252284.html

其实就是分成子树部分(down)和向上的部分(up)来考虑、转移;

要想清楚vis的作用等等,还有那个ed的使用,是和fa配套的,也就是只在子树中使用;

期望就是其他状态的期望和除以总状态数,只要想清楚有些什么状态就很好转移了!

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int const maxn=3e5+;
int n,m,fa[maxn],f[maxn],son[maxn],head[maxn],ct,ed[maxn],cir[maxn],cnt,dfn[maxn],tim,b[maxn];
double down[maxn],up[maxn],ans;
bool vis[maxn];
struct N{
int to,next,w;
N(int t=,int n=,int w=):to(t),next(n),w(w) {}
}edge[maxn];
void add(int x,int y,int z)
{
edge[++ct]=N(y,head[x],z);head[x]=ct;
edge[++ct]=N(x,head[y],z);head[y]=ct;
}
void dfs_down(int x)
{
vis[x]=;int tot=;
for(int i=head[x],v;i;i=edge[i].next)
{
if(vis[v=edge[i].to])continue;
ed[v]=edge[i].w;//
dfs_down(v);tot++;
down[x]+=down[v]+edge[i].w;
}
if(tot)down[x]/=tot;//
son[x]=tot;vis[x]=;//
}
void dfs_up(int x,int u)
{
// fa[x]=u;f[x]=1;
// if(u&&son[u])up[x]+=(up[u]+down[u]*son[u]-down[x]-ed[x])/son[u]+ed[x];
// for(int i=head[x],v;i;i=edge[i].next)
// if(!f[v=edge[i].to])ed[v]=edge[i].w,dfs_up(v,x);
vis[x]=;if(u) f[x]=;
if((son[u]-+f[u])&&u) up[x]+=(up[u]*f[u]+son[u]*down[u]-down[x]-ed[x])/(son[u]-+f[u]);//特判根节点(只有一个son的)
for(int i=head[x],v;i;i=edge[i].next)
if(!vis[v=edge[i].to]) /*ed[i]=edge[i].w,*/
up[v]+=edge[i].w,dfs_up(v,x);//在down时已求出ed
}
void make(int rt,int x)
{
for(int i=x;i!=fa[rt];i=fa[i])//不是i!=rt !!!
cir[++cnt]=i,b[cnt+]=ed[i],f[i]=,vis[i]=;//vis在dfs_down中会用
//犯蠢把 cir[++cnt]=i 写成 cir[++cnt]=x ,调了半天!!!
}
void tarjan(int x,int ff)
{
dfn[x]=++tim;fa[x]=ff;
for(int i=head[x],v;i;i=edge[i].next)
{
if(!dfn[v=edge[i].to])ed[v]=edge[i].w,tarjan(v,x);
else if(dfn[v]>dfn[x])b[]=edge[i].w,make(x,v);
}
}
void solve(int x,int j,int step)
{
double g=0.5,d=;
for(int i=;i<cnt;i++)//所求的都是up[x]!
{
if(step==-)d+=b[j];j+=step;//是b而不是ed
if(j==)j=cnt;if(j==cnt+)j=;
if(step==)d+=b[j];//j+后再+b[j],顺、逆时针有所区分
if(i==cnt-)up[x]+=g*(d+down[cir[j]]);
else up[x]+=g*(d+down[cir[j]])*son[cir[j]]/(son[cir[j]]+);
g/=son[cir[j]]+;
}
}
void work()//!
{
tarjan(,);
for(int i=;i<=cnt;i++)dfs_down(cir[i]),vis[cir[i]]=;//
for(int i=;i<=cnt;i++)solve(cir[i],i,),solve(cir[i],i,-);
for(int i=;i<=cnt;i++)dfs_up(cir[i],);//由于vis,只处理子树
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=,x,y,z;i<=m;i++)
scanf("%d%d%d",&x,&y,&z),add(x,y,z);
if(m==n-)dfs_down(),dfs_up(,);
else work();
for(int i=;i<=n;i++)
ans+=(down[i]*son[i]+up[i]*f[i])/(son[i]+f[i]);
printf("%.5lf",ans/n);//ans/n!
return ;
}

最新文章

  1. 使用IdleTest进行TDD单元测试驱动开发演练(3) 之 ASP.NET MVC
  2. ios导航器跳转动画
  3. docker里重装mysql
  4. 在sqlserver 中with(nolock)详解
  5. STM32的GPIO口的输出开漏输出和推挽输出
  6. Codeforces Educational Codeforces Round 5 E. Sum of Remainders 数学
  7. HTML5本地化应用开发-HTML5 Web存储详解
  8. MapReduce Shuffle And Sort
  9. VMWare11虚拟机安装OSX10.9系统资源下载及问题解决
  10. crawler_http关闭连接
  11. Java设计模式偷跑系列(十二)组合模式建模和实现
  12. 教你成为全栈工程师(Full Stack Developer) 〇-什么是全栈工程师
  13. android adb shell 命令大全
  14. (!(~+[])+{})[--[~+&quot;&quot;][+[]]*[~+[]] + ~~!+[]]+({}+[])[[~!+[]]*~+[]]一行js代码的原理分析
  15. IntelliJ IDEA 导入新项目
  16. 渲染函数render和函数式组件
  17. JS实战
  18. 百度地图插件(百度地图AK申请配置指南)
  19. php 类与对象 面向对象编程 简单例子
  20. 如何解决Visual Studio2010 编译时提示系统找不到指定文件问题

热门文章

  1. 树莓派静态IP配置
  2. css可见性
  3. Centos常用命名
  4. IntelliJ IDEA常用统一设置(Linux/Mac/Windows)
  5. 根据wsdl反向生成webservice服务端(3种方法)
  6. INAPP登陆调用的FB接口
  7. Development of Intel chipsets interconnection
  8. openwrt gstreamer实例学习笔记(一.初始化gstreamer)
  9. MapReduce算法形式四:mapjoin
  10. andfix使用