• codeforces805F Expected diameter of a tree


    题目大意:

    给定一个森林,有若干个询问,每次询问在第i棵树中随机选一个点,在第j棵树中随机选一个点并将它们相连后树的直径的期望值。

    对每棵树求出它的直径d,对每个点求出它到树上最远点的距离f,那么选择x、y点时树的直径就是:

    max(d[i],d[j],f[x]+f[y]+1)

    对每棵树中点的f排序。

    枚举一棵树中每个点,再二分另一棵树的f就能统计答案了。

    具体看代码。

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<map>
    #include<vector>
    using namespace std;
    #define ll long long
    #define N 100010
    vector<int>g[N],e[N];
    vector<ll>Sum[N];
    map<int,double>M[N];
    int f[N],i,j,n,m,x,y,Q,s[N],d[N],a[N],Ma,Y;
    bool Flag;
    double Ans,k;
    inline int Max(int x,int y){return x<y?y:x;}
    inline int Find(int x){return f[x]==x?x:f[x]=Find(f[x]);}
    inline void Dfs1(int x,int p,int s){
        if(Flag)return;
        if(d[x]){Flag=1;return;}
        if(s>Ma)Ma=s,y=x;
        d[x]=Max(d[x],s);
        for(int i=0;i<e[x].size();i++)
        if(e[x][i]!=p)Dfs1(e[x][i],x,s+1);
    }
    inline void Dfs2(int x,int p,int s){
        if(s>Ma)Ma=s,y=x;
        d[x]=Max(d[x],s);
        for(int i=0;i<e[x].size();i++)
        if(e[x][i]!=p)Dfs2(e[x][i],x,s+1);
    }
    inline bool Calc(int x){
        Flag=0;Ma=-1;
        Dfs1(x,0,0);
        if(Flag)return 1;
        Ma=-1;
        Dfs2(y,0,0);
        Dfs2(y,0,0);
        return 0;
    }
    inline int Binary(int x,int y){
        if(g[x][0]>=y)return -1;
        if(g[x][g[x].size()-1]<=y)return g[x].size()-1;
        int l=0,r=g[x].size()-2,Mid;
        while(l<=r){
            Mid=l+r>>1;
            if(g[x][Mid]<=y&&g[x][Mid+1]>=y)return Mid;
            if(g[x][Mid]>y)r=Mid-1;else l=Mid+1;
        }
        return l;
    }
    int main(){
        scanf("%d%d%d",&n,&m,&Q);
        for(i=1;i<=n;i++)f[i]=i;
        for(i=1;i<=m;i++)scanf("%d%d",&x,&y),f[Find(x)]=Find(y),e[x].push_back(y),e[y].push_back(x);
        for(i=1;i<=n;i++){
            if(Find(i)==i&&Calc(i))a[i]=-1;
            s[f[i]]++;
        }
        for(i=1;i<=n;i++)
        if(a[f[i]]!=-1)a[f[i]]=Max(a[f[i]],d[i]),g[f[i]].push_back(d[i]);
        for(i=1;i<=n;i++)
        if(s[i]&&a[i]!=-1){
            sort(g[i].begin(),g[i].end());
            Sum[i].push_back(g[i][0]);
            for(j=1;j<g[i].size();j++)Sum[i].push_back(Sum[i][j-1]+g[i][j]);
        }
        while(Q--){
            scanf("%d%d",&x,&y);
            x=Find(x);y=Find(y);
            if(x==y||a[x]==-1||a[y]==-1){puts("-1");continue;}
            if(s[x]>s[y]||(s[x]==s[y]&&x>y))swap(x,y);
            k=M[x][y];
            if(k){printf("%.9lf
    ",k);continue;}
            Ma=Max(a[x],a[y]);Y=g[y].size();
            for(i=Ans=0;i<g[x].size();i++){
                j=Binary(y,Ma-g[x][i]-1);
                if(j>-1)Ans+=1ll*Ma*(j+1);
                if(j<Y-1)Ans+=Sum[y][Y-1]-(j>-1?Sum[y][j]:0)+1ll*(Y-j-1)*(g[x][i]+1);
            }
            Ans/=1ll*s[x]*s[y];
            M[x][y]=Ans;
            printf("%.9lf
    ",Ans);
        }
        return 0;
    }
    codeforces805F
  • 相关阅读:
    ubuntu 12.04 安装phpUnit
    composer 安装 ubuntu 12.04
    初学 Phreeze 4
    curl模拟文件post提交
    Phreeze Criteria的应用,在两个表里面查找多个符合条件的数据
    ubuntu 12.04 安装vim
    初学Phreeze 5 excel 表格,自动生成文件
    初学Phreeze 6,reporter文件
    //让程序在后台运行,即使关闭终端 仍可运行
    phpopenid中创建多级目录的方法
  • 原文地址:https://www.cnblogs.com/gjghfd/p/6905848.html
Copyright © 2020-2023  润新知