首页 > 其他分享 >游览计划 题解

游览计划 题解

时间:2024-10-06 12:59:55浏览次数:1  
标签:游览 int 题解 复杂度 ne 计划 push dis

题意

给定一张无向图,选取四个点 \(a \ne b \ne c \ne d\),求 \(f(a, b) + f(b, c) + f(c, d)\) 的最大值,其中 \(f(u, v)\) 表示点 \(u\) 到点 \(v\) 的最短路长度。

题解

如果顺着枚举四个点 \(a\)、\(b\)、\(c\)、\(d\),是一个 \(n^4\) 的复杂度,显然过不了。

但是我们发现如果确定了 \(a\)、\(b\)、\(c\),那么 \(d\) 可以贪心找到离 \(c\) 最远的且不为 \(a\)、\(b\) 的点。

复杂度降到了 \(n^3\),但还是过不了(赛时就分析到了这里就没往下想了)。

但 \(b\) 点也同理,\(b\) 点确定了,找最远的 \(a\) 即可。

我们维护一个 \(g(u)\),表示离 \(u\) 点最远的点即可。

但是不对,题目要求 \(a \ne b \ne c \ne d\),倘若 \(g(b) = c\),就无法满足条件,就成功地挂了。

所以我们需要维护一个 \(g(u, 0 \sim 2)\),表示离 \(u\) 最远、次远、次次远的点。

此时就很好解决了。

说说前面的最短路。

如果直接跑弗洛伊德会爆掉,但是由于边权为 \(1\),所以可以跑 \(n\) 次 bfs,时间复杂度从 \(n^3\) 降到了 \(nm\)(赛时这个我也没想到)。

时间复杂度:\(\mathcal O(nm + n^2)\)。

namespace zqh {
const int N = 4005;

int n, m, dis[N][N];
int far[N][3];
vector<int> g[N];

il void bfs(int s) { // 求以 s 为起点的最短路
    queue<int> q;
    q.push(s);
    dis[s][s] = 0;
    while (q.size()) {
        int u = q.front();
        q.pop();
        for (int v : g[u]) {
            if (!dis[s][v]) {
                dis[s][v] = dis[s][u] + 1;
                q.push(v);
            }
        }
    }
}

il void init() {
    cin >> n >> m;
    for (rg int i = 1; i <= m; i++) {
        int x, y;
        cin >> x >> y;
        g[x].push_back(y);
        g[y].push_back(x);
    }
}

il void solve() {
    for (rg int i = 1; i <= n; i++) {
        bfs(i);
        dis[i][0] = -1;
    }
    for (rg int i = 1; i <= n; i++) { // far 就是上文的 g
        for (rg int j = 1; j <= n; j++) {
            // cout << dis[i][j] << " ";
            if (dis[i][j] == 0x3f3f3f3f3f3f3f3f || i == j)
                continue;
            if (dis[i][far[i][2]] < dis[i][j]) { // 一个判前三大的好方法
                far[i][2] = j;
            }
            if (dis[i][far[i][1]] < dis[i][far[i][2]]) {
                swap(far[i][1], far[i][2]);
            }
            if (dis[i][far[i][0]] < dis[i][far[i][1]]) {
                swap(far[i][0], far[i][1]);
            }
        }
        // cout << endl;
    }
    // for (int i = 1; i <= n; i++) {
    //     cout << far[i][0] << " " << far[i][1] << " " << far[i][2] << endl;
    // }
    int ans = 0;
    for (rg int b = 1; b <= n; b++) { 
        for (rg int c = b + 1; c <= n; c++) { // 枚举 b、c
            for (rg int i = 0; i < 3; i++) {
                for (rg int j = 0; j < 3; j++) { // 枚举第几大
                    int a = far[b][i], d = far[c][j];
                    if (a != b && a != c && a != d && b != c && b != d &&
                        c != d) { // 不能重复
                        if (dis[a][b] + dis[b][c] + dis[c][d] > ans) {
                            ans = max(ans, dis[a][b] + dis[b][c] + dis[c][d]); // 统计答案
                            // cout << a << " " << b << " " << c << " " << d
                            //      << endl;
                        }
                    }
                }
            }
        }
    }
    cout << ans;
}

void main() {
    init();
    solve();
}
}  // namespace zqh

标签:游览,int,题解,复杂度,ne,计划,push,dis
From: https://www.cnblogs.com/zphh/p/18449002

相关文章

  • 洛谷 P3523 题解
    洛谷P3523[POI2011]DYN-Dynamite分析二分答案,问题转化为:对于给定的\(K\),选择尽可能少的节点,使得所有关键节点都被「覆盖」。对于一个关键节点,「覆盖」的定义为:存在一个被选择的点与这个关键节点的距离不大于\(K\)。方便起见,我们指定\(1\)号节点是这棵树的根节点。我们......
  • [题解]ABC374 A~E
    A-Takahashisan2直接判断字符串是否以san结尾即可。点击查看代码#include<bits/stdc++.h>usingnamespacestd;intmain(){ strings; cin>>s; intn=s.size(); if(s[n-1]=='n'&&s[n-2]=='a'&&s[n-3]=='s')cout<<&......
  • P11059 [入门赛 #27] 数字 (Hard Ver.)题解
    Solution先读题:在给定x的位数\(n\)和模数\(p\)后,要求构造一个\(x\)在满足\(x\modp\)的余数尽可能小的前提下使\(x\)的数字尽可能小。我们假设\(x\)的各位数字之和为\(m\),有\(1\lem\le9n\)。.(当\(x\)仅在最高位有1时\(m=1\),称为情况一,当x每位为9时\(m=9n\),称为情况二......
  • ABC374E 题解
    好题。爱做。标签:二分。求最大的最小值,考虑二分答案。然后问题就转化成了(求\(n\)次):有两种物品,每种物品有一个代价和价值,求获得不少于给定价值所需的最小代价。下文记物品的代价为\(w\),价值为\(v\),所拿的数量为\(cnt\)。假设有两种物品\(S\)与\(T\),\(S\)物品的性价比......
  • Windows计划任务出现0x1错误结果
    Windows计划任务出现0x1错误结果现象解决方法结果 现象参考不少的文章,基本上都是说因为权限的问题,但试了N次都不行,仍然报0x1的错误结果,亲测解决方法说明如下; 1.脚本本身没问题,手动本地可以执行;2.系统版本Windows10专业工作站版版本号21H2解决方法在设......
  • P10678 『STA - R6』月 题解
    Solution看了别的大佬的题解,感觉都是数学证明然后用树和图做的,看不懂啊。。。萌新瑟瑟发抖用vector模拟树,然后贪心摸索做出来了。注意到要求最深叶子结点和最浅叶子结点的距离最短时的情况,那么此时根节点应该是树中度数最大的点,把树尽可能的拓宽,深度换宽度。那么同理的根节点......
  • 题解:P11008 『STA - R7』异或生成序列
    Solution序列\(p\)是\(1\)~\(n\)的排列,因此考虑搜索回溯。由\(\sumn\le2\times10^6\)得知\(O(n^2)\)会炸,深感遗憾但仍考虑剪枝。坚信深搜过百万的蒟蒻。。。原\(b\)序列为长度\(n-1\)的序列:{\(b_1,b_2,b_3\cdotsb_n-1\)}将其前面插入一个元素\(......
  • 题解:AT_abc374_d [ABC374D] Laser Marking
    看到\(n\le6\),就知道这道题又是一道搜索了。题面有点长,信息也给的有点多,但稍微分析就可以得到只需要搜索印刷线段的顺序即可。具体的,我们在深搜函数里面传\(4\)个参数,分别代表已选线段的数量,当前位置的横纵坐标,以及当前时间。为了方便,我们表示的是已经印刷完当前线段后的时间......
  • P5593 题解
    题目分析首先考虑什么样的颜色能被链覆盖。容易想到当某种颜色恰巧在一条链上会被覆盖。所以只需要判断一种颜色是否能构成链即可,链的贡献也很好计算。算法考虑链的性质:有且仅有两个端点。凭借这个性质,可以判断一种颜色是否在一条链上。在dfs中考虑各种情况。假设一个......
  • P10418 [蓝桥杯 2023 国 A] 相连的边 题解
    一个比较有趣的树形DP,情况比较多。【题目简述】给定一棵树,求三条相连的边,其边权之和最大。【思路】以X代表当前节点,S表示儿子,G表示孙子,P表示父节点。首先把树建出来,在以下图中,我们模拟二号点的DP过程,考虑以下几种情况:有一条边指向父节点时FG(FatherGrandson):一......