zoukankan      html  css  js  c++  java
  • Codeforces Round #343 (Div. 2) E. Famil Door and Roads lca 树形dp

    E. Famil Door and Roads

    题目连接:

    http://www.codeforces.com/contest/629/problem/E

    Description

    Famil Door’s City map looks like a tree (undirected connected acyclic graph) so other people call it Treeland. There are n intersections in the city connected by n - 1 bidirectional roads.

    There are m friends of Famil Door living in the city. The i-th friend lives at the intersection ui and works at the intersection vi. Everyone in the city is unhappy because there is exactly one simple path between their home and work.

    Famil Door plans to construct exactly one new road and he will randomly choose one among n·(n - 1) / 2 possibilities. Note, that he may even build a new road between two cities that are already connected by one.

    He knows, that each of his friends will become happy, if after Famil Door constructs a new road there is a path from this friend home to work and back that doesn't visit the same road twice. Formally, there is a simple cycle containing both ui and vi.

    Moreover, if the friend becomes happy, his pleasure is equal to the length of such path (it's easy to see that it's unique). For each of his friends Famil Door wants to know his expected pleasure, that is the expected length of the cycle containing both ui and vi if we consider only cases when such a cycle exists.

    Input

    The first line of the input contains integers n and m (2 ≤ n,  m ≤ 100 000) — the number of the intersections in the Treeland and the number of Famil Door's friends.

    Then follow n - 1 lines describing bidirectional roads. Each of them contains two integers ai and bi (1 ≤ ai, bi ≤ n) — the indices of intersections connected by the i-th road.

    Last m lines of the input describe Famil Door's friends. The i-th of these lines contain two integers ui and vi (1 ≤ ui, vi ≤ n, ui ≠ vi) — indices of intersections where the i-th friend lives and works.

    Output

    For each friend you should print the expected value of pleasure if he will be happy. Your answer will be considered correct if its absolute or relative error does not exceed 10 - 6.

    Namely: let's assume that your answer is a, and the answer of the jury is b. The checker program will consider your answer correct, if .

    Sample Input

    4 3
    2 4
    4 1
    3 2
    3 1
    2 3
    4 1

    Sample Output

    4.00000000
    3.00000000
    3.00000000

    Hint

    题意

    给一棵树,然后有Q次询问,每次询问给你两个点,问你加一条边之后,这两个点所在的简单环的期望长度是多少

    简单环即这两个点在一个环上,这个环是没有重边的。

    题解:

    两个点u,v,只有3种情况

    1.lca(u,v)=v;

    这种情况的答案等于v上面的点的距离和除以v上面的点数量+u下面的点距离和除以u下面的点数。

    2.lca(u,v)=u;

    同上

    3.lca(u,v)!=u!=v

    这种情况的答案等于v下面的点的距离和除以v下面的点的数量+u下面的点的距离和除以v下面的点的数量。

    下面的点的距离和,这个东西,用树形dp去解决就好了。

    至于上面的点的距离和,假设lca(u,v)=v这种情况,那么sumUp[v]=sumAll[v]-sumDown[z]-sz[z],z点是v到u的那条路径上的v的儿子。

    sumAll[i]是所有点到i点的距离和,sz是这棵子树的大小,sumDown[i]是子树的距离和。

    然后这道题就结束了。

    代码

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn = 1e5+7;
    const int maxm = 20;
    int n,m,sz[maxn],lca[maxn][maxm],deep[maxn];
    long long sumDown[maxn],sumAll[maxn];
    vector<int> E[maxn];
    void dfs(int x,int p)
    {
        sz[x]=1;
        sumDown[x]=0;
        for(int i=0;i<E[x].size();i++)
        {
            int v = E[x][i];
            if(v==p)continue;
            deep[v]=deep[x]+1;
            lca[v][0]=x;
            for(int j=1;j<maxm;j++)
            {
                int fa = lca[v][j-1];
                if(fa==0)continue;
                lca[v][j]=lca[fa][j-1];
            }
            dfs(v,x);
            sumDown[x]+=sumDown[v]+sz[v];
            sz[x]+=sz[v];
        }
    }
    void dfs2(int x,int p)
    {
        for(int i=0;i<E[x].size();i++)
        {
            int v = E[x][i];
            if(v==p)continue;
            sumAll[v]=sumAll[x]+n-2*sz[v];
            dfs2(v,x);
        }
    }
    void build()
    {
        dfs(1,-1);
        sumAll[1]=sumDown[1];
        dfs2(1,-1);
    }
    int up(int x,int d)
    {
        for(int i=maxm-1;i>=0;i--)
        {
            if(d<(1<<i))continue;
            x=lca[x][i];
            d-=(1<<i);
        }
        return x;
    }
    int Lca(int x,int y)
    {
        if(deep[x]>deep[y])swap(x,y);
        y=up(y,deep[y]-deep[x]);
        if(x==y)return x;
        for(int i=maxm-1;i>=0;i--)
        {
            if(lca[x][i]!=lca[y][i])
                x=lca[x][i],y=lca[y][i];
        }
        return lca[x][0];
    }
    void query()
    {
        int x,y;
        scanf("%d%d",&x,&y);
        int v = Lca(x,y);
        double ans = deep[x]+deep[y]-2*deep[v]+1;
        if(x==v)
        {
            int z = up(y,deep[y]-deep[x]-1);
            ans+=(double)(sumAll[x]-sumDown[z]-sz[z])/(n-sz[z]);
        }
        else
            ans+=(double)sumDown[x]/sz[x];
        if(y==v)
        {
            int z = up(x,deep[x]-deep[y]-1);
            ans+=(double)(sumAll[y]-sumDown[z]-sz[z])/(n-sz[z]);
        }
        else
            ans+=(double)sumDown[y]/sz[y];
        printf("%.12f
    ",ans);
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<n;i++)
        {
            int x,y;scanf("%d%d",&x,&y);
            E[x].push_back(y);
            E[y].push_back(x);
        }
        build();
        while(m--)query();
    }
  • 相关阅读:
    全方位深度剖析--性能测试之LoardRunner 介绍
    国外性能测试博客
    由我主讲的软件测试系列视频之性能测试系列视频讲座目录出炉了
    性能测试之系统监控工具nmon
    性能测试学习内容指南
    性能测试之操作系统计数器分析方法
    JAVA正则表达式:Pattern类与Matcher类详解
    (总结)密码破解之王:Ophcrack彩虹表(Rainbow Tables)原理详解(附:120G彩虹表下载)
    border-collapse实现表格细线边框
    安卓造成内存泄露的几个原因
  • 原文地址:https://www.cnblogs.com/qscqesze/p/5205981.html
Copyright © 2011-2022 走看看