2878: [Noi2012]迷失乐园

Time Limit: 10 Sec  Memory Limit: 512 MBSec  Special Judge

Submit: 319  Solved: 223

[Submit][Status]

Description

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

小Z如今所在的大门也正好是一个景点。小Z不知道什么好玩,于是他决定,从当前位置出发,每次随机去一个和当前景点有道路相连的景点。而且同一个景点不去两次(包含起始景点)。贪玩的小Z会一直游玩,直到当前景点的相邻景点都已经訪问过为止。小Z全部经过的景点按顺序构成一条非反复路径,他想知道这条路径的期望长度是多少?小Z把游乐园的抽象地图画下来带回了家,但是忘了标哪个点是大门,他仅仅好如果每一个景点都可能是大门(即每一个景点作为起始点的概率是一样的)。同一时候,他每次在选择下一个景点时会等概率地随机选择一个还没去过的相邻景点。

Input

第一行是两个整数n和m,分别表示景点数和道路数。 接下来行。每行三个整数Xi, Yi, Wi。分别表示第i条路径的两个景点为Xi, Yi,路径长Wi。全部景点的编号从1至n,两个景点之间至多仅仅有一条道路。

Output

共一行。包括一个实数。即路径的期望长度。

Sample Input

4 3


1 2 3

2 3 1

3 4 4

Sample Output

6.00000000



【例子解释】例子数据中共同拥有6条不同的路径: 路径 长度 概率

1-->4 8 1/4

2-->1 3 1/8

2-->4 5 1/8

3-->1 4 1/8

3-->4 4 1/8

4-->1 8 1/4

因此期望长度 = 8/4 + 3/8 + 5/8 + 4/8 + 4/8 + 8/4 = 6.00

【评分方法】本题没有部分分,你程序的输出仅仅有和标准答案的差距不超过0.01时,才干获得该測试点的满分,否则不得分。

【数据规模和约定】对于100%的数据,1 <= Wi <= 100。

測试点编号 n m 备注

1 n=10 m = n-1 保证图是链状

2 n=100 仅仅有节点1的度数大于2

3 n=1000 /

4 n=100000 /

5 n=100000 /

6 n=10 m = n /

7 n=100 环中节点个数<=5

8 n=1000 环中节点个数<=10

9 n=100000 环中节点个数<=15

10 n=100000 环中节点个数<=20

HINT

Source

分析本题发现m=n-1或m=n,且图连通.

故图为树或环加外向树

树:

对节点x。考虑向下走和向上走两种情况。期望分别为down[x]和up[x]

环加外向树:

对环上每棵树的down[],同上

考虑环上节点的up[]。k^2大暴力硬算

非环节点的up[]。可由环上节点up[]求出,方法仍同上

PS:考虑“无路可走”时,期望=0.0

在本题中有vector的erase(q.begin(),q.begin()+k)函数使用方法(删除[0,k)区间)

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<functional>
#include<iostream>
#include<cmath>
#include<cctype>
#include<ctime>
#include<vector>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=pre[x];p;p=next[p])
#define Lson (x<<1)
#define Rson ((x<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,127,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define INF (2139062143)
#define F (100000007)
#define MAXN (100000+10)
#define MAXM (300000+10)
long long mul(long long a,long long b){return (a*b)%F;}
long long add(long long a,long long b){return (a+b)%F;}
long long sub(long long a,long long b){return (a-b+(a-b)/F*F+F)%F;}
typedef long long ll;
typedef long double ld; int n,m,edge[MAXM],pre[MAXN]={0},next[MAXM]={0},weight[MAXM],size=0;
void addedge(int u,int v,int w){edge[++size]=v;weight[size]=w;next[size]=pre[u],pre[u]=size;}
void addedge2(int u,int v,int w){addedge(u,v,w),addedge(v,u,w);}
long double up[MAXN]={0.0},down[MAXN]={0.0};
int fa[MAXN]={0},son[MAXN]={0};
void dfs_down(int x)
{
Forp(x)
{
int v=edge[p];
if (v^fa[x])
{
fa[v]=x;son[x]++;
dfs_down(v);
down[x]+=(ld)(weight[p]+down[v]);
}
}
if (son[x]) down[x]/=(ld)son[x];
}
void dfs_up(int x)
{
ld sum=0.0;
Forp(x)
{
int v=edge[p];
if (v^fa[x])
{
sum+=(ld)weight[p]+down[v];
}
}
if (fa[x]) sum+=up[x];
Forp(x)
{
int v=edge[p];
if (v^fa[x])
{
up[v]=sum-(ld)weight[p]-down[v];
if ((son[x]-(!fa[x]))) up[v]/=(son[x]-(!fa[x]));
up[v]+=(ld)weight[p];
dfs_up(v);
}
}
}
bool b[MAXN]={0},b2=0;
vector<int> q,q2;
void print()
{
/* cout<<q.size()<<endl;
Rep(i,q.size()) cout<<q[i]<<' ';cout<<endl;
cout<<q2.size()<<endl;
Rep(i,q2.size()) cout<<q2[i]<<' ';cout<<endl;
*/
}
void find_circle(int x)
{
b[x]=1;q.push_back(x);
Forp(x)
{
int v=edge[p];
if (!b[v])
{
q2.push_back(weight[p]);find_circle(v);
if (b2) return;
}
else if (q[q.size()-2]^v)
{
int k=0;
while(q[k]^v) k++;
print();
q.erase(q.begin(),q.begin()+k);
q2.erase(q2.begin(),q2.begin()+k);
q2.push_back(weight[p]);
b2=1;return;
}
}
q.pop_back();q2.pop_back();
}
void circle_down()
{
int size=q.size();
Rep(i,size)
{
int x=q[i];
ld sum=0.0;
Forp(x)
{
int v=edge[p];
if ((v^q[(i-1+size)%size])&&v^(q[(i+1)%size]))
{
fa[v]=x;son[x]++;
dfs_down(v);
down[x]+=(ld)(weight[p]+down[v]);
}
}
if (son[x]) down[x]/=(ld)son[x];
}
}
void circle_up()
{
int size=q.size();
Rep(i,size)
{
int x=q[i];
//处理环
ld p=1.0/(ld)(2),w_past=0.0;
For(j,size-1)
{
w_past+=q2[(i+j-1)%size];
int v=q[(i+j)%size];
if (j!=size-1) up[x]+=p*son[v]/(ld)(son[v]+1)*(w_past+down[v]);
else up[x]+=p*(w_past+down[v]);
p/=(ld)son[v]+1;
}
p=1.0/(ld)(2),w_past=0.0;
For(j,size-1)
{
w_past+=q2[(i-j+size)%size];
int v=q[(i-j+size)%size];
if (j!=size-1) up[x]+=p*son[v]/(ld)(son[v]+1)*(w_past+down[v]);
else up[x]+=p*(w_past+down[v]);
p/=(ld)son[v]+1;
}
//处理子节点
ld sum=0.0;
Forp(x)
{
int v=edge[p];
if ((v^q[(i-1+size)%size])&&v^(q[(i+1)%size]))
{
sum+=(ld)weight[p]+down[v];
}
}
Forp(x)
{
int v=edge[p];
if ((v^q[(i-1+size)%size])&&v^(q[(i+1)%size]))
{
up[v]=sum-(ld)weight[p]-down[v];
up[v]/=(ld)(son[x]+1);
up[v]+=(2.0/(ld)(son[x]+1))*up[x];
up[v]+=(ld)weight[p];
dfs_up(v);
}
} }
}
int main()
{
// freopen("bzoj2878.in","r",stdin);
// freopen("bzoj2878.out","w",stdout);
scanf("%d%d",&n,&m);
For(i,m)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
addedge2(u,v,w);
}
// For(i,n)
// Forp(i) cout<<i<<' '<<edge[p]<<' '<<weight[p]<<endl;
cout.setf(ios::fixed);
cout.precision(5); if (m==n-1)
{
dfs_down(1);dfs_up(1);
// For(i,n) cout<<i<<":"<<down[i]<<' '<<up[i]<<endl;
ld ans=0.0;
For(i,n) if (fa[i]) ans+=((ld)son[i]*down[i]+up[i])/(son[i]+1);
else ans+=down[i];
ans/=(ld)n;
cout<<ans<<endl;
}
else
{
find_circle(1);
print();
circle_down();
circle_up();
// For(i,n) cout<<i<<':'<<down[i]<<' '<<up[i]<<endl; MEM(b);
Rep(i,q.size()) b[q[i]]=1;
ld ans=0.0;
For(i,n)
if (b[i]) ans+=2.0/(ld)(son[i]+2)*up[i]+(ld)(son[i])/(ld)(son[i]+2)*down[i];
else ans+=1.0/(ld)(son[i]+1)*up[i]+(ld)(son[i])/(ld)(son[i]+1)*down[i];
ans/=(ld)n;
cout<<ans<<endl;
} return 0;
}

版权声明:本文博主原创文章,博客,未经同意不得转载。

BZOJ 2878([Noi2012]-失落的游乐园树DP+出站年轮加+后市展望DP+vector的erase)的更多相关文章

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

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

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

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

  3. bzoj 2878 [Noi2012]迷失游乐园——树上的期望dp

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2878 很好的树上概率题的思路,就是分成up和down. 代码中有众多小细节.让我弃疗好几天的 ...

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

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

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

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

  6. 【BZOJ】【2878】【NOI2012】迷失游乐园

    树形+基环树DP/数学期望 然而我并不会做…… 题解戳这里:http://blog.csdn.net/u011265346/article/details/46328543 好吧先考虑一个简单点的,当 ...

  7. BZOJ.5287.[AHOI HNOI2018]毒瘤(虚树 树形DP)

    BZOJ LOJ 洛谷 设\(f[i][0/1]\)表示到第\(i\)个点,不选/选这个点的方案数.对于一棵树,有:\[f[x][0]=\prod_{v\in son[x]}(f[v][0]+f[v] ...

  8. BZOJ 2286 [Sdoi2011]消耗战(虚树+树形DP)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2286 [题目大意] 出一棵边权树,每次给出一些关键点,求最小边割集, 使得1点与各个关 ...

  9. bzoj 4006 管道连接 —— 斯坦纳树+状压DP

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4006 用斯坦纳树求出所有关键点的各种连通情况的代价,把这个作为状压(压的是集合选择情况)的初 ...

随机推荐

  1. 京东评论情感分类器(基于bag-of-words模型)

    京东评论情感分类器(基于bag-of-words模型) 近期在本来在研究paraVector模型,想拿bag-of-words来做对照. 数据集是京东的评论,经过人工挑选,选出一批正面和负面的评论. ...

  2. 阶乘因式分解(一)(南阳oj56)

    阶乘因式分解(一) 时间限制:3000 ms  |  内存限制:65535 KB 难度:2 描写叙述 给定两个数m,n,当中m是一个素数. 将n(0<=n<=10000)的阶乘分解质因数, ...

  3. Android从无知到有知——NO.7

    的ip拨号器在监听外拨电话时用的是系统提供的广播事件.而有些时候我们须要自己设定广播事件来满足特定的须要. Ok,今天整一下自己定义广播事件,我们用一个状态监測模块向一个3G模块发送报警信息来实现这一 ...

  4. 数据结构之计算器的实现(JAVA)(四)

    原理: 1.将中序表达式变化兴许表达式 2.当前字符为数字,将该数字放入栈中 3.当前字符为操作符,从栈中取出两个树,依据操作符来运算,将运算结果放入到栈中 4.反复,直到将字符操作完.此时栈中仅仅剩 ...

  5. Android -- Looper.prepare()和Looper.loop() —深度版

    Android中的Looper类,是用来封装消息循环和消息队列的一个类,用于在android线程中进行消息处理.handler事实上能够看做是一个工具类.用来向消息队列中插入消息的. (1) Loop ...

  6. MySQL InnoDB存储引擎undo redo解析

    本文介绍MySQL数据库InnoDB存储引擎重做日志漫游 00 – Undo Log Undo Log 为了实现事务原子,在MySQL数据库InnoDB存储引擎,还使用Undo Log(简称:MVCC ...

  7. 直接选择排序----java实现

    直接选择排序思路: 从待排序数据中选择第一个假定为最小的下标,然后他后面的与他循环比较,得到真的最小值下标,然后最小值前的那一区段依次后移,并把最小值赋值给第一个元素.第二次时,假定第二个为最小,然后 ...

  8. 流量计算-Jstorm提交Topology过程(下一个)

    马上部分流量计算-Jstorm提交Topology过程(上), 5.上篇任务已经ServiceHandler.submitTopologyWithOpts()方法.在该方法中,会实例化一个Topolo ...

  9. ASP.NET分页正品—分页真

     承接上篇博文<ASP.NET真假分页-假分页>:http://blog.csdn.net/u010773667/article/details/38845009,继续解说ASP.NE ...

  10. Session小案例------完成用户登录

    Session小案例------完成用户登录     在项目开发中,用户登陆功能再平常只是啦,当用户完毕username和password校验后.进入主界面,须要在主界面中显示用户的信息,此时用ses ...