题目链接

基环树套路题。(然而各种错误调了好久233)

当$m=n-1$时,原图是一棵树。

先以任意点为根做$dp$,求出从每一个点出发,然后只往自己子树里走时路径的期望长度。

接着再把整棵树再扫一遍,求出从每一个点出发时路径的期望长度。

最后再统计一遍答案即可。

当$m=n$时,原图是一棵基环树。

先找到图中那唯一的一个环,然后以环上的每一个节点为根在此节点的子树内做$dp$。

环上节点的数量很少,$dp$之后直接暴力算出从每一个环上节点出发时路径的期望长度。

然后把每一个环上节点的子树扫一遍,求出从每一个点出发时路径的期望长度。

最后再统计一遍答案即可。

#include<iostream>
#include<cstdio>
#include<fstream>
using namespace std;
struct edge
{
int last;
int end;
int weight;
}e[200005];
int n=0,m=0,root=0;
int ne=1,cnt[100005],note[100005];
int tot=0,ring[100005];
int ringdis[100005];
bool flag=false,vis[100005],inring[100005];
double ans=0,f[100005],d[100005];
void NewEdge(int u,int v,int w)
{
ne++;
e[ne].last=note[u];
e[ne].end=v;
e[ne].weight=w;
note[u]=ne;
}
void dfs(int x,int fx)
{
cnt[x]=f[x]=0;
for(int i=note[x];i;i=e[i].last)
{
if(e[i].end==fx||inring[e[i].end]) continue;
dfs(e[i].end,x),cnt[x]++;
}
if(cnt[x]==0) return;
for(int i=note[x];i;i=e[i].last)
{
if(e[i].end==fx||inring[e[i].end]) continue;
f[x]+=e[i].weight+f[e[i].end];
}
f[x]/=cnt[x];
}
void dfss(int x,int fx,int w)
{
if(x==root&&!inring[x]) d[x]=f[x];
else if(x!=root)
{
d[x]=f[x]*cnt[x]/(cnt[x]+1);
if(fx==root&&cnt[fx]==1) d[x]+=(double)w/(cnt[x]+1);
else if(fx==root) d[x]+=((d[fx]*cnt[fx]-f[x]-w)/(cnt[fx]-1)+w)/(cnt[x]+1);
else d[x]+=((d[fx]*(cnt[fx]+1)-f[x]-w)/cnt[fx]+w)/(cnt[x]+1);
}
for(int i=note[x];i;i=e[i].last)
{
if(e[i].end==fx||inring[e[i].end]) continue;
dfss(e[i].end,x,e[i].weight);
}
}
void dfsss(int x,int fe)
{
if(flag) return;
vis[x]=true,ring[++tot]=x;
for(int i=note[x];i;i=e[i].last)
{
if(i==(fe^1)) continue;
if(flag) break;
if(vis[e[i].end])
{
int st=0,ed=tot,h=e[i].end;
for(int i=1;i<=tot;i++)
if(ring[i]==h) {st=i;break;}
for(int i=st;i<=ed;i++)
{
inring[ring[i]]=true;
for(int j=note[ring[i]];j;j=e[j].last)
if(e[j].end==((i==ed)?ring[st]:ring[i+1]))
{ringdis[i]=e[j].weight;break;}
}
for(int i=st;i<=ed;i++) dfs(ring[i],0);
for(int i=st;i<=ed;i++)
{
int x=ring[i];
d[x]=f[x]*cnt[x]/(cnt[x]+2);
int u=i,w=0;
double p=1;
for(;;)
{
p/=cnt[ring[u]]+((u==i)?2:1),w=ringdis[u];
u=((u+1>ed)?st:(u+1));
if(((u+1>ed)?st:(u+1))==i)
{d[x]+=p*(f[ring[u]]+w); break;}
else d[x]+=p*(f[ring[u]]*cnt[ring[u]]/(cnt[ring[u]]+1)+w);
}
u=i,w=0,p=1;
for(;;)
{
p/=cnt[ring[u]]+((u==i)?2:1),w=ringdis[(u-1<st)?ed:(u-1)];
u=((u-1<st)?ed:(u-1));
if(((u-1<st)?ed:(u-1))==i)
{d[x]+=p*(f[ring[u]]+w); break;}
else d[x]+=p*(f[ring[u]]*cnt[ring[u]]/(cnt[ring[u]]+1)+w);
}
}
for(int i=st;i<=ed;i++)
cnt[ring[i]]+=2,root=ring[i],dfss(root,0,0);
flag=true; break;
}
dfsss(e[i].end,i);
}
tot--;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
int u=0,v=0,w=0;
scanf("%d%d%d",&u,&v,&w);
NewEdge(u,v,w);
NewEdge(v,u,w);
}
if(m==n-1) root=1,dfs(root,0),dfss(root,0,0);
else dfsss(1,0);
for(int i=1;i<=n;i++)
ans+=(double)1/n*d[i];
printf("%.5f",ans);
return 0;
}

Luogu P2081

Luogu P2081 [NOI2012]迷失游乐园 | 期望 DP 基环树的更多相关文章

  1. 【题解】Luogu P2081 [NOI2012]迷失游乐园

    原题传送门 这是当时冬令营课上讲的题,咕咕咕到了现在 如果这题没有环套树的话,就很套路了 需要两个数组up[i]和down[i],down[i]表示从i点第一步向下走的期望距离,up[i]表示从i点第 ...

  2. BZOJ 2878: [Noi2012]迷失游乐园( 树形dp )

    一棵树的话直接树形dp(求出往下走和往上走的期望长度). 假如是环套树, 环上的每棵树自己做一遍树形dp, 然后暴力枚举(环上的点<=20)环上每个点跑经过环上的路径就OK了. -------- ...

  3. [luogu2081 NOI2012] 迷失游乐园 (树形期望dp 基环树)

    传送门 题目描述 放假了,小Z觉得呆在家里特别无聊,于是决定一个人去游乐园玩. 进入游乐园后,小Z看了看游乐园的地图,发现可以将游乐园抽象成有n个景点.m条道路的无向连通图,且该图中至多有一个环(即m ...

  4. bzoj 2878: [Noi2012]迷失游乐园【树上期望dp+基环树】

    参考:https://blog.csdn.net/shiyukun1998/article/details/44684947 先看对于树的情况 设d[u]为点u向儿子走的期望长度和,du[u]为u点的 ...

  5. bzoj2878 [Noi2012]迷失游乐园 [树形dp]

    Description 放假了,小Z认为呆在家里特别无聊.于是决定一个人去游乐园玩. 进入游乐园后.小Z看了看游乐园的地图,发现能够将游乐园抽象成有n个景点.m条道路的无向连通图,且该图中至多有一个环 ...

  6. [bzoj2878][Noi2012]迷失游乐园(基环树dp)

    [bzoj2878][Noi2012]迷失游乐园(基环树dp) bzoj luogu 题意:一颗数或是基环树,随机从某个点开始一直走,不走已经到过的点,求无路可走时的路径长期望. 对于一棵树: 用两个 ...

  7. 【BZOJ 2878】 2878: [Noi2012]迷失游乐园 (环套树、树形概率DP)

    2878: [Noi2012]迷失游乐园 Description 放假了,小Z觉得呆在家里特别无聊,于是决定一个人去游乐园玩.进入游乐园后,小Z看了看游乐园的地图,发现可以将游乐园抽象成有n个景点.m ...

  8. bzoj 2878: [Noi2012]迷失游乐园

    #include<iostream> #include<cstring> #include<cstdio> #define M 100005 #define ld ...

  9. Hdu第八场 树形dp+基环树

    Card Game 每个牌背面的数字朝正面的数字连一条有向边 则题目变为问你最少翻转多少次 能使得每个数字的入度不超过1 首先判断图中每个连通块是不是树或者基环树 因为只有树或者基环树能使得每个点的入 ...

随机推荐

  1. FastAPI(6)- get 请求 - 详解 Query

    可选参数 上一篇文章讲过查询参数可以不是必传的,可以是可选参数 from fastapi import FastAPI from typing import Optional import uvico ...

  2. Django学习day03随堂笔记

    每日测验 """ 今日考题 1.什么是静态文件,django静态文件配置如何配置,如何解决接口前缀不断变化,html页面上路径的引用需要反复修改的问题 2.request ...

  3. 浅聊Linux的五种IO模型

    在日常 Coding 中,多多少少都会接触到网络 IO,就会想要深入了解一下.看了很多文章,总是云里雾里的感觉,直到读了<UNIX网络编程 卷1:套接字联网API>中的介绍后,才豁然开朗. ...

  4. span标签的巧用

    前言: 用struts的标签结合<td>标签将后台数据在表格里渲染了出来,目前需求是需要将两个状态组合在一起显示 解决:通过span标签在td里的套用可以实现 <logic:notE ...

  5. 👊 Spring技术原理系列-从零开始教你SpringEL表达式使用和功能分析讲解指南(上篇)

    Spring EL表达式语言,这种语言jsp中学到的el,但是在整个spring之中其表达式语言要更加的复杂,而且支持度更加的广泛,最重要的是他可以进行方法的调用,对象的实例化,集合操作等等,但是唯一 ...

  6. HashMap扩容和ConcurrentHashMap

    HashMap 存储结构 HashMap是数组+链表+红黑树(1.8)实现的. (1)Node[] table,即哈希桶数组.Node是内部类,实现了Map.Entry接口,本质是键值对. stati ...

  7. 解决 Asp.Net5 在视频文件下载预览时无法快进的问题

    前情提要 https://www.cnblogs.com/puzhiwei/p/15265005.html 在解决.Net5 如何修改Content-Disposition实现在线预览的功能后,我又遇 ...

  8. Win10下部署VS+Qt+OpenCV+darknet(YOLO)集成环境

    VS+Qt集成环境 下载VS与Qt并安装. VS:官网链接 Qt:下载链接 将Qt的bin目录加入PATH路径 bin目录举例:D:\development\Qt\5.12.0\msvc2017_64 ...

  9. logback日志入门超级详细讲解

    基本信息 日志:就是能够准确无误地把系统在运行状态中所发生的情况描述出来(连接超时.用户操作.异常抛出等等): 日志框架:就是集成能够将日志信息统一规范后输出的工具包. Logback优势 Logba ...

  10. 自然语言处理标注工具——Brat(安装、测试、使用)

    一.Brat标注工具安装 1.安装条件: (1)运行于Linux系统(window系统下虚拟机内linux系统安装也可以) (2)目前brat最新版本(v1.3p1)仅支持python2版本运行使用( ...