zoukankan      html  css  js  c++  java
  • 【BZOJ 3470】3470: Freda’s Walk 期望

    3470: Freda’s Walk

    Time Limit: 1 Sec  Memory Limit: 128 MB
    Submit: 42  Solved: 22

    Description

    雨后的Poetic Island空气格外清新,于是Freda和Rainbow出来散步。 Poetic Island的交通可以看作一张n个点、m 边的有向无环图。由于刚下过雨,每条边都有一个积水深度,而恰好Freda 和Rainbow都喜欢踩水玩儿,于是Ta们从某个点出发,选择走向哪条边的概率与该边的积水深度是成正比的。即:如果Freda和Rainbow现在在点u,点u 出发的所有边的积水深度之和为s,从u到v的边积水深度为w,那么Ta们选择走向v的概率就是 w/s。  
    Ta们会一直走下去,直到到达一个没有出边的点,那么散步的路程长度就是走过的边的数量。更特殊的是,Freda和Rainbow在出发之前还可以选择一条边,在散步过程中无视这条边的存在(当然也可以不选择)。请你帮忙计算一下,Ta 们从0号点出发,散步的路程长度的期望值最大是多少?  

    Input

    第一行两个正整数 n、m。 
    接下来m行每行三个整数u、v、w,表示从u到v有一条无向边,积水深度为w。 
     
     

    Output


    输出Freda和Rainbow散步的路程长度的最大期望值,四舍五入保留六位小数。

    Sample Input

    4 5
    0 1 2
    0 2 1
    0 3 3
    1 3 1
    2 3 4

    Sample Output

    2.000000

    HINT

    对于  100% 的数据,2<=n<=10000,1<=m<=100000,0<=u,v<n,1<=w<=1000。

    Source

    【分析】

      测试考这题。。错误打法 考场上竟然AC了【黑人问号脸??

      也算给自己提个醒吧,DAG和树终究是不一样的。不能f[i][0]和f[i][1]表示后面割还是没割,比如:

      

      割3后面那条边是f[2][1]和f[3][1],但是不会让他们转移到f[1][1],因为你规定只有一个儿子可以选割,但是是可以的,因为只是个割了3下面那条边。。

      所以这个方法不行。

      考虑割一条边对答案的影响。

      假设割x->y,只会影响f[x]以及1到x路径上的点。

      但是我们只需要知道x的f值的改变对1这个点的f值的影响。

      假设从1走到x的概率是p,假设那么f[1]会增加(f[x]'-f[x])*p,直接枚举割哪条边然后计算出这个求max就好了。

      【ORZORZORZ...

     1 #include<cstdio>
     2 #include<cstdlib>
     3 #include<cstring>
     4 #include<iostream>
     5 #include<algorithm>
     6 #include<cmath>
     7 using namespace std;
     8 #define Maxn 100010
     9 #define Maxm 1000010
    10 
    11 struct node
    12 {
    13     int x,y,c,next,p;
    14 }t[Maxm],tt[Maxm];
    15 int first[Maxn],len;
    16 int d[Maxn];
    17 
    18 int ft[Maxn];
    19 void ins(int x,int y,int c)
    20 {
    21     t[++len].x=x;t[len].y=y;t[len].c=c;
    22     t[len].next=first[x];first[x]=len;t[len].p=1;
    23     tt[len].x=y;tt[len].y=x;tt[len].c=c;tt[len].next=ft[y];ft[y]=len;
    24 }
    25 
    26 bool vis[Maxn];
    27 double g[Maxn];
    28 void dfs2(int x)
    29 {
    30     if(vis[x]) return;vis[x]=1;
    31     if(x==1) {g[x]=1;return;}
    32     for(int i=ft[x];i;i=tt[i].next)
    33     {
    34         int y=tt[i].y;
    35         dfs2(y);
    36         g[x]+=g[y]*tt[i].c*1.0/d[y];
    37     }
    38 }
    39 
    40 double f[Maxn];
    41 void dfs(int x)
    42 {
    43     if(vis[x]) return;vis[x]=1;
    44     f[x]=0;
    45     for(int i=first[x];i;i=t[i].next) if(t[i].p)
    46     {
    47         int y=t[i].y;
    48         dfs(y);
    49         f[x]+=(f[y]+1)*t[i].c*1.0/d[x];
    50     }
    51     return;
    52 }
    53 
    54 int main()
    55 {
    56     int n,m;
    57     scanf("%d%d",&n,&m);
    58     len=0;
    59     memset(first,0,sizeof(first));
    60     memset(ft,0,sizeof(ft));
    61     for(int i=1;i<=m;i++)
    62     {
    63         int x,y,c;
    64         scanf("%d%d%d",&x,&y,&c);
    65         x++;y++;
    66         d[x]+=c;
    67         ins(x,y,c);
    68     }
    69     memset(vis,0,sizeof(vis));
    70     for(int i=1;i<=n;i++) g[i]=0;
    71     for(int i=1;i<=n;i++) dfs2(i);
    72     memset(vis,0,sizeof(vis));
    73     dfs(1);
    74     double mx=f[1];
    75     for(int i=1;i<=len;i++)
    76     {
    77         int x=t[i].x,y=t[i].y;
    78         double ad;
    79         if(d[x]!=t[i].c) ad=(f[x]*d[x]*1.0/(d[x]-t[i].c)-(f[y]+1)*t[i].c*1.0/(d[x]-t[i].c))-f[x];
    80         else ad=-f[x];
    81         mx=max(mx,f[1]+g[x]*ad);
    82     }
    83     printf("%.6lf
    ",mx);
    84     return 0;
    85 }
    View Code

    2017-04-24 18:51:22

  • 相关阅读:
    前端开发者也可以酷酷地开发桌面程序
    V部落,V人事
    jq 正方体旋转
    jq 实现旋转木马
    jquery 获取元素(父节点,子节点,兄弟节点)
    Vue.js面试题整理
    Java面试必备技能
    在前后端分离的SpringBoot项目中集成Shiro权限框架
    正则表达式大全
    Docker容器日志查看与清理
  • 原文地址:https://www.cnblogs.com/Konjakmoyu/p/6758374.html
Copyright © 2011-2022 走看看