zoukankan      html  css  js  c++  java
  • Codeforces 840D Expected diameter of a tree 分块思想

    Expected diameter of a tree

    我们先两次dfs计算出每个点能到达最远点的距离。

    暴力计算两棵树x, y连边直径的期望很好求, 我们假设SZ(x) < SZ(y)

    我们枚举 x 的每个端点, 二分找到分界点, 复杂度为SZ(x) * log(SZ(y))

    其实我们对于每次询问我们记忆化一下就可以啦。

    这是因为对于SZ(x)小于 sqrt(n)的询问, 我们直接暴力求就好啦, 复杂度q * SZ(x) * log(SZ(y))

    对于SZ(x) > sqrt(n) 这样的 x , 个数绝对不超过sqrt(n)所以如果两两之间的答案全部算出来的

    最坏复杂度是sqrt(n) * sqrt(n) / 2 * sqrt(n) * log(n) == n * sqrt(n) * log(n) 。 所以直接记忆化就好啦。

    #include<bits/stdc++.h>
    #define LL long long
    #define LD long double
    #define ull unsigned long long
    #define fi first
    #define se second
    #define mk make_pair
    #define PLL pair<LL, LL>
    #define PLI pair<LL, int>
    #define PII pair<int, int>
    #define SZ(x) ((int)x.size())
    #define ALL(x) (x).begin(), (x).end()
    #define fio ios::sync_with_stdio(false); cin.tie(0);
    
    using namespace std;
    
    const int N = 1e5 + 7;
    const int inf = 0x3f3f3f3f;
    const LL INF = 0x3f3f3f3f3f3f3f3f;
    const int mod = 1e9 + 7;
    const double eps = 1e-8;
    const double PI = acos(-1);
    
    template<class T, class S> inline void add(T& a, S b) {a += b; if(a >= mod) a -= mod;}
    template<class T, class S> inline void sub(T& a, S b) {a -= b; if(a < 0) a += mod;}
    template<class T, class S> inline bool chkmax(T& a, S b) {return a < b ? a = b, true : false;}
    template<class T, class S> inline bool chkmin(T& a, S b) {return a > b ? a = b, true : false;}
    
    const int B = 330;
    
    map<PII, LL> Map;
    int treecnt, belong[N];
    vector<int> tree[N];
    vector<LL> sum[N];
    
    int n, m, q, maxdis[N], dia[N], son[N];
    vector<int> G[N];
    bool root[N];
    
    void dfs(int u, int fa, int idx) {
        belong[u] = idx;
        son[idx]++;
        for(auto& v : G[u]) {
            if(v == fa) continue;
            dfs(v, u, idx);
            chkmax(maxdis[u], maxdis[v] + 1);
        }
    }
    
    void dfs2(int u, int fa, int maxup) {
        chkmax(maxdis[u], maxup + 1);
        int mx0 = maxup, mx1 = -inf;
        for(auto& v : G[u]) {
            if(v == fa) continue;
            if(maxdis[v] > mx0) mx1 = mx0, mx0 = maxdis[v];
            else if(maxdis[v] > mx1) mx1 = maxdis[v];
        }
        for(auto& v : G[u]) {
            if(v == fa) continue;
            if(maxdis[v] == mx0) dfs2(v, u, mx1 + 1);
            else dfs2(v, u, mx0 + 1);
        }
    }
    
    LL calc(int u, int v) {
        LL ans = 0;
        LL maxdia = max(dia[u], dia[v]);
        for(auto& d : tree[u]) {
            int p = upper_bound(ALL(tree[v]), maxdia - d - 1) - tree[v].begin();
            ans += p * maxdia;
            if(p < SZ(tree[v])) {
                ans += (SZ(tree[v]) - p) * (d + 1) + sum[v].back();
                if(p - 1 >= 0) ans -= sum[v][p - 1];
            }
        }
        return ans;
    }
    
    int main() {
        scanf("%d%d%d", &n, &m, &q);
        for(int i = 1; i <= m; i++) {
            int u, v; scanf("%d%d", &u, &v);
            G[u].push_back(v);
            G[v].push_back(u);
        }
        for(int i = 1; i <= n; i++)
            if(!belong[i]) dfs(i, 0, ++treecnt), root[i] = true;
        for(int i = 1; i <= n; i++) if(root[i]) dfs2(i, 0, -1);
        for(int i = 1; i <= n; i++) {
            tree[belong[i]].push_back(maxdis[i]);
            chkmax(dia[belong[i]], maxdis[i]);
        }
        for(int i = 1; i <= treecnt; i++) {
            sort(ALL(tree[i]));
            sum[i].resize(SZ(tree[i]));
            sum[i][0] = tree[i][0];
            for(int j = 1; j < SZ(sum[i]); j++)
                sum[i][j] = sum[i][j - 1] + tree[i][j];
        }
        for(int i = 1; i <= q; i++) {
            int u, v; scanf("%d%d", &u, &v);
            u = belong[u]; v = belong[v];
            if(son[u] > son[v]) swap(u, v);
            if(u == v) {
                puts("-1");
            } else {
                if(Map.find(mk(u, v)) == Map.end()) Map[mk(u, v)] = calc(u, v);
                printf("%.12f
    ", 1.0 * Map[mk(u, v)] / son[u] / son[v]);
            }
        }
        return 0;
    }
    
    /*
    */
  • 相关阅读:
    Leetcode 92. Reverse Linked List II
    Leetcode 206. Reverse Linked List
    Leetcode 763. Partition Labels
    Leetcode 746. Min Cost Climbing Stairs
    Leetcode 759. Employee Free Time
    Leetcode 763. Partition Labels
    搭建数据仓库第09篇:物理建模
    Python进阶篇:Socket多线程
    Python进阶篇:文件系统的操作
    搭建数据仓库第08篇:逻辑建模–5–维度建模核心之一致性维度2
  • 原文地址:https://www.cnblogs.com/CJLHY/p/10747108.html
Copyright © 2011-2022 走看看