BZOJ 2878: [Noi2012]迷失游乐园

Writing now。

  1 /**************************************************************
  2     Problem: 2878
  3     User: zrts
  4     Language: C++
  5     Result: Accepted
  6     Time:588 ms
  7     Memory:10748 kb
  8 ****************************************************************/
  9
 10 #include<iostream>
 11 #include<cstdio>
 12 #include<algorithm>
 13 #include<cstring>
 14 #include<vector>
 15 //by zrt
 16 //problem:
 17 using namespace std;
 18 typedef long long LL;
 19 const int inf(0x3f3f3f3f);
 20 const double eps(1e-9);
 21 bool oncircle[100005];
 22 int du[100005];
 23 int fa[100005];
 24 int H[100005],X[200005],P[200005],tot;
 25 double E[200005];
 26 inline void add(int x,int y,int z){//add an edge
 27     P[++tot]=y;X[tot]=H[x];H[x]=tot;E[tot]=z;
 28 }
 29 int n,m;
 30 double F[100005];//for son E
 31 double D[100005];// F * |son|
 32 double p[100005];// ans
 33 int num[100005];// |son|
 34 int pre[100005];
 35 double wpre[100005];
 36 bool type;
 37 void treedp1(int x){//Dp the tree first
 38     for(int i=H[x];i;i=X[i]){
 39         if(P[i]==fa[x]||oncircle[P[i]]) continue;
 40         fa[P[i]]=x;
 41         treedp1(P[i]);
 42         D[x]+=F[P[i]]+E[i];num[x]++;
 43     }
 44     if(num[x])
 45     F[x]=D[x]/num[x];
 46     else F[x]=0;
 47 }
 48 void treedp2(int x,double edge){//Dp the tree second | calc the P
 49     double other;
 50     if(!fa[fa[x]]) {
 51         if(!type){
 52             if(num[fa[x]]>1) other=(p[fa[x]]*(num[fa[x]]+0)-edge-F[x])/(num[fa[x]]-1)+edge;
 53             else other=edge;
 54         }else{
 55             other=(p[fa[x]]*(num[fa[x]]+2)-edge-F[x])/(num[fa[x]]+1)+edge;
 56         }
 57     }
 58     else other=(p[fa[x]]*(num[fa[x]]+1)-edge-F[x])/num[fa[x]]+edge;
 59
 60     p[x]=(other+D[x])/(num[x]+1);
 61     for(int i=H[x];i;i=X[i]){
 62         if(P[i]==fa[x]||oncircle[P[i]]) continue;
 63         treedp2(P[i],E[i]);
 64     }
 65 }
 66 vector<int> circle;
 67 bool ok;
 68 int nxt[100005];double wnxt[100005];
 69 void findcircle(int x,int fa){
 70     for(int i=H[x];i;i=X[i]){
 71         if(P[i]==fa) continue;
 72         if(pre[P[i]]){
 73             ok=1;
 74             int k=x;
 75             pre[P[i]]=x;
 76             wpre[P[i]]=E[i];
 77             do{
 78                 oncircle[k]=1;
 79                 circle.push_back(k);
 80                 k=pre[k];
 81             }while(k!=P[i]);
 82             oncircle[k]=1;
 83             circle.push_back(k);
 84         }else{
 85             pre[P[i]]=x;wpre[P[i]]=E[i];
 86             findcircle(P[i],x);
 87             if(ok) return;
 88         }
 89     }
 90 }
 91 double calc_nxt(int now,int end){
 92     double ret=wnxt[now];
 93     now=nxt[now];
 94     int extra=0;
 95     if(nxt[now]!=end) ret+=calc_nxt(now,end)/(du[now]-1);
 96     else extra=-1;
 97     for(int i=H[now];i;i=X[i]){
 98         if(oncircle[P[i]]) continue;
 99         ret+=(E[i]+F[P[i]])/(du[now]-1+extra);
100     }
101     return ret;
102 }
103 double calc_pre(int now,int end){
104     double ret=wpre[now];
105     now=pre[now];
106     int extra=0;
107     if(pre[now]!=end) ret+=calc_pre(now,end)/(du[now]-1);
108     else extra=-1;
109     for(int i=H[now];i;i=X[i]){
110         if(oncircle[P[i]]) continue;
111         ret+=(E[i]+F[P[i]])/(du[now]-1+extra);
112     }
113     return ret;
114 }
115 int main(){// the main function
116     #ifdef LOCAL
117     freopen("in.txt","r",stdin);
118     freopen("out.txt","w",stdout);
119     #endif
120     scanf("%d%d",&n,&m);
121     for(int i=0,x,y,z;i<m;i++){
122         scanf("%d%d%d",&x,&y,&z);
123         du[x]++;
124         du[y]++;
125         add(x,y,z);
126         add(y,x,z);
127     }
128     if(m==n-1){
129         treedp1(1);
130         p[1]=F[1];
131         for(int i=H[1];i;i=X[i]){
132             treedp2(P[i],E[i]);
133         }
134         double ans=0;
135         for(int i=1;i<=n;i++){
136              ans+=p[i];
137         }
138         printf("%.5f\n",ans/n);
139     }else{
140         type=1;
141         pre[1]=-1;
142         findcircle(1,-1);
143         for(int now=0;now<circle.size();now++){
144             nxt[pre[circle[now]]]=circle[now];
145             wnxt[pre[circle[now]]]=wpre[circle[now]];
146         }
147         for(int now=0;now<circle.size();now++){
148             for(int i=H[circle[now]];i;i=X[i]){
149                 if(oncircle[P[i]]) continue;
150                 treedp1(P[i]);
151                 p[circle[now]]+=(F[P[i]]+E[i])/du[circle[now]];
152                 num[circle[now]]++;
153             }
154         }
155         for(int now=0;now<circle.size();now++){
156             p[circle[now]]+=(calc_pre(circle[now],circle[now])+calc_nxt(circle[now],circle[now]))/du[circle[now]];
157         }
158         for(int now=0;now<circle.size();now++){
159             for(int i=H[circle[now]];i;i=X[i]){
160                 if(oncircle[P[i]]) continue;
161                 fa[P[i]]=circle[now];
162                 treedp2(P[i],E[i]);
163             }
164         }
165         double ans=0;
166         for(int i=1;i<=n;i++){
167             ans+=p[i];
168         }
169         printf("%.5f\n",ans/n);
170     }
171     return 0;
172 }

时间: 2024-10-13 02:03:21

BZOJ 2878: [Noi2012]迷失游乐园的相关文章

BZOJ 2878([Noi2012]迷失游乐园-树形DP+环加外向树+期望DP+vector的erase)

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现在所在的大门也正好是

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

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

BZOJ 2878 [Noi2012]迷失游乐园 树形期望DP+基环树

题意:链接 方法:树形期望DP+基环树 解析: 首先先看前50%的数据 是一棵树 那么我们可以搞树形DP 然后设几个正常的数组 sum[i]代表i走i的子节点的期望的和. down[i]代表从底下走到i的期望. size[i]代表i的儿子个数 up[i]代表从i往上走的期望 然后就可以推式子了 显而易见地可以推出来up的式子 然后有一些奇怪的关于根节点的特判,注意一下就OK了. 然后后50% 我们发现它是一个基环树? 那么首先可以乱搞出来环上的点,然后记录一下这个环上的点的连接方式,求一下相邻两

【BZOJ 2878】 [Noi2012]迷失游乐园

2878: [Noi2012]迷失游乐园 Time Limit: 10 Sec  Memory Limit: 512 MBSec  Special Judge Submit: 415  Solved: 283 [Submit][Status] Description 放假了,小Z觉得呆在家里特别无聊,于是决定一个人去游乐园玩.进入游乐园后,小Z看了看游乐园的地图,发现可以将游乐园抽象成有n个景点.m条道路的无向连通图,且该图中至多有一个环(即m只可能等于n或者n-1).小Z现在所在的大门也正好是

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

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如今所在的大门也正好

NOI2012 迷失游乐园

http://www.lydsy.com/JudgeOnline/problem.php?id=2878 比较容易的概率题. Case1~5: 这是一棵树. 我们求出每个点i度数du[i],只走子树的期望距离g[i]和不走子树的期望距离f[i],这比较好求. 然后累加即可. Case6~10: 图中有一个环,然后环上的点都是一棵树的根. 对于每棵树,我们同样求出每个点i度数du[i],只走子树的期望距离g[i]. 那么怎么求不走子树的期望距离f[i]呢? 我们先求环上的点的f[i]吧. 我们枚举

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

Description 放假了,小Z认为呆在家里特别无聊.于是决定一个人去游乐园玩. 进入游乐园后.小Z看了看游乐园的地图,发现能够将游乐园抽象成有n个景点.m条道路的无向连通图,且该图中至多有一个环(即m仅仅可能等于n或者n-1).小Z如今所在的大门也正好是一个景点. 小Z不知道什么好玩,于是他决定,从当前位置出发,每次随机去一个和当前景点有道路相连的景点,而且同一个景点不去两次(包括起始景点).贪玩的小Z会一直游玩.直到当前景点的相邻景点都已经訪问过为止.小Z全部经过的景点按顺序构成一条非反

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

bzoj luogu 题意:一颗数或是基环树,随机从某个点开始一直走,不走已经到过的点,求无路可走时的路径长期望. 对于一棵树: 用两个$dp$数组分别记录从这个点起向上向下走的期望 向下走的$dp$不用多说 向上走的$dp$: 对于从$u$计算$v$的dp $dp[v]$应当是从u向周围引出所有路径减去走向t的路径的期望后再除以$deg_{u}-1$ 对于基环树: 环上的点很少. 此时环上的点的向上$dp$指从u出发向环上两头走的期望. 如何计算:对于环上每一个点都向环的两头各dp一次取平均值

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

树形+基环树DP/数学期望 然而我并不会做…… 题解戳这里:http://blog.csdn.net/u011265346/article/details/46328543 好吧先考虑一个简单点的,当m=n-1时,整个是一个树形的结构,无根树我们一般还是转成有根树来处理……然后既然是无法回头的,那么我们可以定一下方向:向下或者向上(废话) 定义一下: son[x]为x的儿子的数量 down[x]表示从x这个点出发,向叶子们走的期望长度. 怎么算呢?其实就是所有可能的情况(所有的儿子)加起来,再求