zoukankan      html  css  js  c++  java
  • 十字星座

    Description

    星空中有 (n) 颗星星,有 (n-1) 对星星间被人为地连上了线,每条连线有各自的长度。所有星星被连成了一个整体。现在,你要在星系中找到一个最大的十字形星座。即,你要找到两条星星构成的路径,使得它们恰好有一颗公共星(这颗公共星不能是某条路径的端点),且两条路径的长度和最大。

    Solution

    很好的题。
    显然对于公共点 (u) 来说,只有下面两种可能的路径方案:

    • (u) 与往下的路径最长的四个儿子组成一对路径。
      这里写图片描述

    • (u) 与往下的路径最长的三个儿子、以及 (u) 的父亲组成一对路径。
      这里写图片描述

    于是

    • 第一遍 (dfs) ,处理出 (u) 往下的最长的四个路径,(f[u][0],f[u][1],f[u][2],f[u][3])
    • 第二遍 (dfs) ,处理出 (u) 往上走的最长路径 (g[u]) 。往上走有两种方案,要么继续往上走,要么走到 (u) 的某个兄弟。
    • 第三遍 (dfs) 更新答案, (ans = max(sum _{i = 0} ^{3}f[u][i],sum _{i = 0} ^{2}f[u][i] + g[u]))

    每个点最多被访问 (3) 次,所以复杂度为 (O(n))
    详见代码。不同的实现方法常数、代码复杂度差别较大。

    #include<bits/stdc++.h>
    using namespace std;
    
    #define N 200001
    #define rep(i, a, b) for (int i = a; i <= b; i++)
    #define drp(i, a, b) for (int i = a; i >= b; i--)
    #define fech(i, x) for (int i = 0; i < x.size(); i++)
    #define ll long long
    
    inline int read() {
        int x = 0, flag = 1; char ch = getchar(); while (!isdigit(ch)) { if (!(ch ^ '-')) flag = -1; ch = getchar(); }
        while (isdigit(ch)) x = (x << 1) + (x << 3) + ch - '0', ch = getchar(); return x * flag;
    }
    
    int n;
    struct edge { int u, v, w; } eg[N]; int tot;
    vector<int> tr[N]; int siz[N];
    #define gte edge e = eg[tr[u][i]]
    int f[N][6], g[N], ans = -1;
    
    bool cmp(int x, int y) { return x > y; }
    void dfsf(int u, int fr) {
        fech(i, tr[u]) {
            gte; if(!(e.v ^ fr)) continue;
            siz[u]++, dfsf(e.v, u), f[u][4] = f[e.v][0] + e.w, sort(f[u], f[u] + 5, cmp);
        }
    }
    
    void dfsg(int u, int fr) {
        fech(i, tr[u]) {
            gte; if(!(e.v ^ fr)) continue;
            if(f[u][0] ^ (f[e.v][0] + e.w)) g[e.v] = max(g[u], f[u][0]) + e.w;
            else g[e.v] = max(g[u], f[u][1]) + e.w;
            dfsg(e.v, u);
        }
    }
    
    void dfs(int u, int fr) {
        int t = 0; rep(i, 0, 3) t += f[u][i];
        if(siz[u] > 3) ans = max(ans, t);
        if(siz[u] > 2 && fr) ans = max(ans, t - f[u][3] + g[u]);
        fech(i, tr[u]) { gte; if(e.v ^ fr) dfs(e.v, u); }
    }
    
    int main() {
        n = read(); rep(i, 2, n) {
            int u = read(), v = read(), w = read();
            eg[++tot] = edge { u, v, w }; tr[u].push_back(tot);
            eg[++tot] = edge { v, u, w }; tr[v].push_back(tot);
        }
        dfsf(1, 0); dfsg(1, 0); dfs(1, 0); cout << ans; return 0;
    }
    
  • 相关阅读:
    【转】构建高并发高可用的电商平台架构实践
    【转】深入解析浏览器的幕后工作原理
    【转】解释器,树遍历解释器,基于栈与基于寄存器
    EasyDarwin返回401 Unauthorized解决方法
    【转】SDP file
    音频PCM格式
    H264相关知识
    testNG之异常测试
    testNG之组测试
    testNG之顺序执行
  • 原文地址:https://www.cnblogs.com/aziint/p/8416372.html
Copyright © 2011-2022 走看看