BZOJ2878 NOI2012迷失游乐园(树形dp+环套树+概率期望)
考虑树的部分分怎么做。令f[i]为i向子树内走的期望路径长度,转移比较显然。算答案时先把其父亲的答案弄好就可以统计自己的答案了。
环套树也类似。树里直接dp,对环上点暴力考虑环上的每条路径,算完后再在树里统计答案。
说起来不是很难。事实上想清楚了也确实不是很难。
不明白为什么不管啥题我都能把代码写的贼长。
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
int read()
{
int x=,f=;char c=getchar();
while (c<''||c>'') {if (c=='-') f=-;c=getchar();}
while (c>=''&&c<='') x=(x<<)+(x<<)+(c^),c=getchar();
return x*f;
}
#define N 100010
int n,m,p[N],degree[N],nxtlen[N],t=-;
int dfn[N],low[N],top=,cnt=,tot=,circle[N];
bool flag[N<<],iscircle[N<<];
double f[N],g[N],ans=;
struct data{int to,nxt,len;
}edge[N<<];
void addedge(int x,int y,int z){t++;edge[t].to=y,edge[t].nxt=p[x],edge[t].len=z,p[x]=t;}
void dfs(int k,int from)
{
for (int i=p[k];~i;i=edge[i].nxt)
if (edge[i].to!=from&&!iscircle[edge[i].to])
{
dfs(edge[i].to,k);
degree[k]++;
f[k]+=f[edge[i].to]+edge[i].len;
}
if (degree[k]) f[k]/=degree[k];
}
void getans(int k,int from)
{
for (int i=p[k];~i;i=edge[i].nxt)
if (edge[i].to!=from)
{
g[edge[i].to]=(f[edge[i].to]*degree[edge[i].to]+edge[i].len+(g[k]*(degree[k]+(k>))-f[edge[i].to]-edge[i].len)/(degree[k]-(k==)))/(degree[edge[i].to]+);
getans(edge[i].to,k);
}
}
void getans2(int k,int from)
{
for (int i=p[k];~i;i=edge[i].nxt)
if (edge[i].to!=from&&!iscircle[edge[i].to])
{
g[edge[i].to]=(f[edge[i].to]*degree[edge[i].to]+edge[i].len+(g[k]*(degree[k]++(k==from))-f[edge[i].to]-edge[i].len)/(degree[k]+(k==from)))/(degree[edge[i].to]+);
getans2(edge[i].to,k);
}
}
void tarjan(int k,int from)
{
dfn[k]=low[k]=++cnt;
for (int i=p[k];~i;i=edge[i].nxt)
if (edge[i].to!=from)
{
if (!dfn[edge[i].to]) tarjan(edge[i].to,k),low[k]=min(low[k],low[edge[i].to]);
else low[k]=min(low[k],dfn[edge[i].to]);
if (low[edge[i].to]>dfn[k]) flag[i]=flag[i^]=;
}
}
void findcircle(int k)
{
circle[++tot]=k;iscircle[k]=;
for (int i=p[k];~i;i=edge[i].nxt)
if (!iscircle[edge[i].to]&&!flag[i]) findcircle(edge[i].to);
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("bzoj2878.in","r",stdin);
freopen("bzoj2878.out","w",stdout);
#endif
n=read(),m=read();
memset(p,,sizeof(p));
for (int i=;i<=m;i++)
{
int x=read(),y=read(),z=read();
addedge(x,y,z),addedge(y,x,z);
}
if (m==n-)
{
dfs(,);
g[]=f[];
if (degree[]>) getans(,);
else g[edge[p[]].to]=(f[edge[p[]].to]*degree[edge[p[]].to]+edge[p[]].len)/(degree[edge[p[]].to]+),getans(edge[p[]].to,);
for (int i=;i<=n;i++) ans+=g[i];
}
else
{
for (int i=;i<=n;i++) if (!dfn[i]) tarjan(i,i);
for (int i=;i<=n;i++)
{
for (int j=p[i];~j;j=edge[j].nxt)
if (!flag[j]) {findcircle(i);break;}
if (tot) break;
}
for (int i=;i<=tot;i++)
for (int j=p[circle[i]];~j;j=edge[j].nxt)
if (edge[j].to==circle[i%tot+]) nxtlen[i]=edge[j].len;
for (int i=;i<=tot;i++) dfs(circle[i],circle[i]);
for (int i=;i<=tot;i++)
{
double P=;
int x=i%tot+,sum=nxtlen[i];
while (x!=i)
{
if (degree[circle[x]])
{
g[circle[i]]+=P*degree[circle[x]]/(degree[circle[x]]+(x%tot+!=i))*(f[circle[x]]+sum);
P/=(degree[circle[x]]+);
}
else if (x%tot+==i) g[circle[i]]+=P*sum;
sum+=nxtlen[x];
x=x%tot+;
}
}
for (int i=;i<=tot;i++)
{
double P=;
int x=i>?i-:tot,sum=nxtlen[x];
while (x!=i)
{
if (degree[circle[x]])
{
g[circle[i]]+=P*degree[circle[x]]/(degree[circle[x]]+((x>?x-:tot)!=i))*(f[circle[x]]+sum);
P/=(degree[circle[x]]+);
}
else if ((x>?x-:tot)==i) g[circle[i]]+=P*sum;
x=x>?x-:tot;
sum+=nxtlen[x];
}
g[circle[i]]+=f[circle[i]]*degree[circle[i]];
g[circle[i]]/=degree[circle[i]]+;
getans2(circle[i],circle[i]);
}
for (int i=;i<=n;i++) ans+=g[i];
}
printf("%.5lf",ans/n);
return ;
}
BZOJ2878 NOI2012迷失游乐园(树形dp+环套树+概率期望)的更多相关文章
- bzoj2878 [Noi2012]迷失游乐园 [树形dp]
Description 放假了,小Z认为呆在家里特别无聊.于是决定一个人去游乐园玩. 进入游乐园后.小Z看了看游乐园的地图,发现能够将游乐园抽象成有n个景点.m条道路的无向连通图,且该图中至多有一个环 ...
- BZOJ 2878: [Noi2012]迷失游乐园( 树形dp )
一棵树的话直接树形dp(求出往下走和往上走的期望长度). 假如是环套树, 环上的每棵树自己做一遍树形dp, 然后暴力枚举(环上的点<=20)环上每个点跑经过环上的路径就OK了. -------- ...
- [bzoj2878][Noi2012]迷失游乐园(基环树dp)
[bzoj2878][Noi2012]迷失游乐园(基环树dp) bzoj luogu 题意:一颗数或是基环树,随机从某个点开始一直走,不走已经到过的点,求无路可走时的路径长期望. 对于一棵树: 用两个 ...
- 【BZOJ-1040】骑士 树形DP + 环套树 + DFS
1040: [ZJOI2008]骑士 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 3312 Solved: 1269[Submit][Status ...
- [BZOJ2878][NOI2012]迷失游乐园(环套树DP+概率)
推荐讲解:https://www.cnblogs.com/Tunix/p/4561493.html 首先考虑树的情况,就是经典的树上概率DP.先DP出down表示从这个点向儿子走能走的期望长度,再DP ...
- BZOJ 1040 树形DP+环套树
就是有n个点n条边,那么有且只有一个环那么用Dfs把在环上的两个点找到.然后拆开,从这条个点分别作树形Dp即可. #include <cstdio> #include <cstrin ...
- BZOJ2878 [Noi2012]迷失游乐园 【基环树 + 树形dp + 期望dp】
题目链接 BZOJ2878 题解 除了实现起来比较长,思维难度还是挺小的 观察数据范围发现环长不超过\(20\),而我们去掉环上任何一个点就可以形成森林 于是乎我们枚举断掉的点,然后只需求出剩余每个点 ...
- [luogu2081 NOI2012] 迷失游乐园 (树形期望dp 基环树)
传送门 题目描述 放假了,小Z觉得呆在家里特别无聊,于是决定一个人去游乐园玩. 进入游乐园后,小Z看了看游乐园的地图,发现可以将游乐园抽象成有n个景点.m条道路的无向连通图,且该图中至多有一个环(即m ...
- bzoj2878 [Noi2012]迷失游乐园——概率期望DP
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2878 这个博客写得很好:https://www.cnblogs.com/qt666/p/72 ...
随机推荐
- SourceTree跳过注册安装使用
%LocalAppData%\Atlassian\SourceTree\目录 创建一个accounts.json [ { "$id": "1", ...
- python爬虫之解析库正则表达式
上次说到了requests库的获取,然而这只是开始,你获取了网页的源代码,但是这并不是我们的目的,我们的目的是解析链接里面的信息,比如各种属性 @href @class span 抑或是p节点里 ...
- 在eclipse中修改项目发布tomcat的路径名
第一种.右键点击项目,选中Properties 第二种.双击tomcat 保存 第三种.修改项目目录下的 .setting目录下的
- Netty源码分析第6章(解码器)---->第2节: 固定长度解码器
Netty源码分析第六章: 解码器 第二节: 固定长度解码器 上一小节我们了解到, 解码器需要继承ByteToMessageDecoder, 并重写decode方法, 将解析出来的对象放入集合中集合, ...
- Mysql读写分离——主从数据库+Atlas
mysql集群 最近在参加项目开发微信小程序后台,由于用户数量巨大,且后台程序并不是很完美,所以对用户的体验很是不友好(简单说就是很卡).赶巧最近正在翻阅<大型网站系统与Java中间件实践> ...
- JavaScript学习(1)之JavaScript基础
JavaScript学习(1)之JavaScript基础 由于工作原因,开发语言逐渐以JavaScript为主,所以,抽空学习了下JavaScript语法.等现阶段的工作稳定之后,陆续会分享下自己在学 ...
- 【一】,python简单爬虫实现
一: 1.获取当前页的课程名称,地址:https://www.ichunqiu.com/courses/webaq 2.选取其中一门课程名称查看源代码: 代码如下: <p class=" ...
- API验证
API验证说明 API验证: a. 发令牌: 静态 PS: 隐患 key被别人获取 b. 动态令牌 PS: (问题越严重)用户生成的每个令牌被黑客获取到,都会破解 c. 高级版本 PS: 黑客网速快, ...
- 字幕字体滚动插件——scroxt.js
README scroxt.js Overview scroxt.js是一个字体滚动的插件库,包括视频弹幕滚动,直播弹幕.直播弹幕强制模式.单行水平左右滚动.文本垂直滚动上下,用于简单快捷生成滚动字体 ...
- UVALive 7464 Robots(模拟)
7464Robots Write a program to collect data from robots. We are given two sets of robotsX=fX1;:::;Xmg ...