zoukankan      html  css  js  c++  java
  • 【JZOJ4890】【NOIP2016提高A组集训第14场11.12】随机游走

    题目描述

    YJC最近在学习图的有关知识。今天,他遇到了这么一个概念:随机游走。随机游走指每次从相邻的点中随机选一个走过去,重复这样的过程若干次。YJC很聪明,他很快就学会了怎么跑随机游走。为了检验自己是不是欧洲人,他决定选一棵树,每条边边权为1,选一对点s和t,从s开始随机游走,走到t就停下,看看要走多长时间。但是在走了10000000步之后,仍然没有走到t。YJC坚信自己是欧洲人,他认为是因为他选的s和t不好,即从s走到t的期望距离太长了。于是他提出了这么一个问题:给一棵n个点的树,问所有点对(i,j)(1≤i,j≤n)中,从i走到j的期望距离的最大值是多少。YJC发现他不会做了,于是他来问你这个问题的答案。

    数据范围

    对于30%的数据,满足n≤5。
    对于50%的数据,满足n≤3000。
    对于100%的数据,满足n≤100000。

    解法

    预处理出每条边的期望长度;
    然后树形动态规划。

    代码

    #include<iostream>
    #include<stdio.h>
    #include<string.h>
    #include<math.h>
    #include<algorithm>
    #define ll long long
    using namespace std;
    const char* fin="rw.in";
    const char* fout="rw.out";
    const int inf=0x7fffffff;
    const int maxn=100007,maxm=maxn*2;
    int n,i,j,k;
    int fi[maxn],la[maxm],ne[maxm],tot;
    int f[maxn],g[maxn];
    int h[maxn][4],ans,id[maxn][4];
    void add_line(int a,int b){
        tot++;
        ne[tot]=fi[a];
        la[tot]=b;
        fi[a]=tot;
    }
    void getf(int v,int from){
        int i,j=0,k;
        for (k=fi[v];k;k=ne[k]) j++;
        f[v]=j;
        for (k=fi[v];k;k=ne[k])
            if (la[k]!=from){
                getf(la[k],v);
                f[v]+=f[la[k]];
            }
    }
    void getg(int v,int from){
        int i,j=0,k;
        for (k=fi[v];k;k=ne[k])
            if (la[k]!=from) j+=1+f[la[k]];
            else j+=1+g[v];
        for (k=fi[v];k;k=ne[k])
            if (la[k]!=from){
                g[la[k]]=j-f[la[k]];
                getg(la[k],v);
            }
    }
    void dfs(int v,int from){
        int i,j,k;
        h[v][0]=h[v][1]=h[v][2]=h[v][3]=0;
        for (k=fi[v];k;k=ne[k])
            if (la[k]!=from){
                dfs(la[k],v);
                i=g[la[k]]+h[la[k]][0];
                j=f[la[k]]+h[la[k]][1];
                if (i>h[v][0]){
                    id[v][0]=la[k];
                    h[v][2]=h[v][0];
                    h[v][0]=i;
                }else h[v][2]=max(h[v][2],i);
                if (j>h[v][1]){
                    id[v][1]=la[k];
                    h[v][3]=h[v][1];
                    h[v][1]=j;
                }else h[v][3]=max(h[v][3],j);
            }
        if (id[v][0]!=id[v][1]) ans=max(ans,h[v][0]+h[v][1]);
        else ans=max(ans,max(h[v][0]+h[v][3],h[v][2]+h[v][1]));
    }
    int main(){
        freopen(fin,"r",stdin);
        freopen(fout,"w",stdout);
        scanf("%d",&n);
        for (i=1;i<n;i++){
            scanf("%d%d",&j,&k);
            add_line(j,k);
            add_line(k,j);
        }
        getf(1,0);
        getg(1,0);
        dfs(1,0);
        printf("%d.00000",ans);
        return 0;
    }

    启发

    从固定长度开始推期望值。

  • 相关阅读:
    继承项目第13周项目1基类中成员的访问限定符和派生类的继承方式
    架构业务wait和sleep区别狭义jiavaBean规范,三层架构模式
    文件文本编辑器ASP.net使用CKEditor(html文本编辑器)
    彩信对象android(5)_发彩信操作
    方法接口UML统一建模语言,java中七种设计原则,
    jquery实现jQuery实现图片轮播效果,jQuery实现焦点新闻
    设备文件BSP及嵌入式驱动开发笔记
    Invalidate
    C#集合类使用范例
    判断一段程序是由C 编译程序还是由C++编译程序编译的
  • 原文地址:https://www.cnblogs.com/hiweibolu/p/6714834.html
Copyright © 2011-2022 走看看