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


    参考:https://blog.csdn.net/shiyukun1998/article/details/44684947
    先看对于树的情况
    设d[u]为点u向儿子走的期望长度和,du[u]为u点的度数,f[u]为u向儿子走的期望长度,只需要dfs两遍,一次求向儿子的d[u]+=f[e[i].to]+e[i].va;,第二次求向父亲走的情况d[e[i].to]+=(d[u]-e[i].va-f[e[i].to])/max(1,du[u]-1)+e[i].va;(u表示向父亲走之后能再向父亲的非u儿子走)
    至于环上的情况,向儿子和树一样,问题在于环点向父亲的情况,因为这可能沿着环走下去,所以先求完向儿子的,然后d加上沿着环走下去的期望
    然后对于每个环点像处理树一样践行第二次dfs即可

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int N=100005;
    int n,m,h[N],cnt,du[N],root,v[N],ti,fa[N];
    double d[N],f[N],g[N],gg[N],ans;
    bool ci[N];
    struct qwe
    {
        int ne,to;
        double va;
    }e[N<<1];
    int read()
    {
        int r=0,f=1;
        char p=getchar();
        while(p>'9'||p<'0')
        {
            if(p=='-')
                f=-1;
            p=getchar();
        }
        while(p>='0'&&p<='9')
        {
            r=r*10+p-48;
            p=getchar();
        }
        return r*f;
    }
    void add(int u,int v,int w)
    {
        cnt++;
        e[cnt].ne=h[u];
        e[cnt].to=v;
        e[cnt].va=w;
        h[u]=cnt;
    }
    void dfs1(int u,int fa)
    {
        for(int i=h[u];i;i=e[i].ne)
            if(e[i].to!=fa&&!ci[e[i].to])
            {
                du[u]++;
                dfs1(e[i].to,u);
                d[u]+=f[e[i].to]+e[i].va;
            }
        if(du[u])
            f[u]=d[u]/(double)du[u];
        if(u!=root)
            du[u]++;
    }
    void dfs2(int u,int fa)
    {
        for(int i=h[u];i;i=e[i].ne)
            if(e[i].to!=fa&&!ci[e[i].to])
            {
                d[e[i].to]+=(d[u]-e[i].va-f[e[i].to])/max(1,du[u]-1)+e[i].va;
                dfs2(e[i].to,u);
            }
    }
    void zhao(int u)
    {
        v[u]=++ti;
        for(int i=h[u];i;i=e[i].ne)
            if(e[i].to!=fa[u])
            {
                if(!v[e[i].to])
                    fa[e[i].to]=u,zhao(e[i].to);
                else if(v[e[i].to]<v[u])
                {
                    for(int j=u;j!=e[i].to;j=fa[j])
                        ci[j]=1;
                    ci[e[i].to]=1;
                }
            }
    }
    void wk(int u,int fa)
    {
        bool fl=0;
        g[u]=0;
        for(int i=h[u];i;i=e[i].ne)
            if(e[i].to!=root&&e[i].to!=fa&&ci[e[i].to])
            {
                fl=1;
                wk(e[i].to,u);
                g[u]+=g[e[i].to]+e[i].va;
            }
        if(u==root)
            return;
        double k=du[u]+(du[u]==0);
        if(!fl)
            g[u]=d[u]/k;
        else
            k=du[u]+1,g[u]=(g[u]+d[u])/k;
    }
    int main()
    {
        n=read(),m=read();
        for(int i=1;i<=m;i++)
        {
            int x=read(),y=read(),z=read();
            add(x,y,z),add(y,x,z);
        }
        if(m==n-1)
        {
            root=1;
            dfs1(1,0);
            dfs2(1,0);
        }
        else
        {
            zhao(1);
            for(int i=1;i<=n;i++)
                if(ci[i])
                    root=i,dfs1(i,0);
            for(int i=1;i<=n;i++)
                if(ci[i])
                    root=i,wk(i,0),gg[i]=g[i];
            for(int i=1;i<=n;i++)
                if(ci[i])
                    du[i]+=2,d[i]+=gg[i];
            for(int i=1;i<=n;i++)
                if(ci[i])
                    root=i,dfs2(i,0);
        }
        for(int i=1;i<=n;i++)
            ans+=d[i]/(double)du[i];
        printf("%.5lf
    ",ans/(double)n);
        return 0;
    }
    
  • 相关阅读:
    中国一些web service收藏
    DataSet 和 List<T> 相互 转换
    JS图表
    IIS DirectoryEntry
    JS弹框
    Remoting
    Del SVN Configuare File BAT
    Viewport3D对象转换成图片
    在WPF中进行碰撞检测
    Button自定义样式
  • 原文地址:https://www.cnblogs.com/lokiii/p/9281678.html
Copyright © 2020-2023  润新知