首页 > 其他分享 >37. CF-Weights Distributing

37. CF-Weights Distributing

时间:2023-03-10 15:23:08浏览次数:52  
标签:cur int 短路 37 Distributing vector Weights 100 dis

链接

这是一个比较经典的题目。容易想到求出两段路径重合的部分,然后贪心的放权值。那么跑三次最短路,枚举重合部分的端点即可。

正解没什么好说的。这题有趣的地方在于,如果数据比较弱,可能会把一些错误做法放过去。

一种错误做法是:只求 \(a\) 点和 \(c\) 点的单源最短路,然后在枚举端点的时候,认为端点一定在 \(a,b\) 或者 \(b,c\) 之间的最短路径上。这个结论是错误的,可以构造出这样的反例:

7 8 1 4 6
1 2 3 4 100 100 100 100
1 2
2 3
3 4
3 5
5 6
3 7
1 7
6 7

这里的答案显然是 \(13\),而错误做法可能会得到 \(111\)。

这种构造的依据是最短路并不是唯一的。然而,即便最短路是唯一的,上面的做法依然不正确。不妨设 \(a,b\) 与 \(b,c\) 两条最短路径共用了从点 \(m\) 到点 \(b\) 的路径,\(m\) 到 \(a,b,c\) 三个点的距离分别为 \(100,10,100\),而在这两条路径外面有一个点 \(n\),它到三个点的距离分别为 \(90,30,90\),那么这个 \(n\) 点在上面的做法中是不会被遍历到的,但只需设计好权值,就可以使最优解经过这个点。

下面是正解的代码,最短路用 BFS 实现更好。

#include <bits/stdc++.h>
using namespace std;
#define pb push_back
using ll = long long;
const int maxn = 2e5 + 5;
const ll inf = 1e18;
vector<int> g[maxn];
void solve() {
    int n, m, A, B, C;
    cin >> n >> m >> A >> B >> C;
    vector<ll> w(m);
    for (auto& i : w) cin >> i;
    for (int i = 1, u, v; i <= m; ++i) {
        cin >> u >> v;
        g[u].pb(v);
        g[v].pb(u);
    }
    sort(w.begin(), w.end());
    vector<int> disA(n + 1, 0x3f3f3f3f);
    vector<int> disB(n + 1, 0x3f3f3f3f);
    vector<int> disC(n + 1, 0x3f3f3f3f);
    vector<int> p(n + 1);
    function<void(int, vector<int>&)> dijkstra = [&](int s, vector<int>& d) {
        vector<int> vis(n + 1, 0);
        struct node {
            int id, dis;
            bool operator < (const node& rhs) const {
                return (dis == rhs.dis ? id > rhs.id : dis > rhs.dis);
            }
        };
        priority_queue<node> q;
        d[s] = 0;
        q.push({ s, 0 });
        while (!q.empty()) {
            auto [cur, cost] = q.top();
            q.pop();
            if (vis[cur]) continue;
            vis[cur] = 1;
            d[cur] = cost;
            for (auto to : g[cur]) {
                if (vis[to]) continue;
                if (d[to] > d[cur] + 1) {
                    d[to] = d[cur] + 1;
                    q.push({ to, d[to] });
                    p[to] = cur;
                }
            }
        }
    };
    vector<ll> pre(m + 1, 0);
    for (int i = 1; i <= m; ++i) {
        pre[i] = pre[i - 1] + w[i - 1];
    }
    dijkstra(A, disA);
    dijkstra(B, disB);
    dijkstra(C, disC);
    ll ans = inf;
    for (int i = 1; i <= n; ++i) {
        int da = disA[i], db = disB[i], dc = disC[i];
        if (da + db + dc > m) continue;
        ans = min(ans, pre[db] + pre[da + db + dc]);
    }
    cout << ans << endl;
    for (int i = 1; i <= n; ++i) {
        g[i].clear();
    }
}
int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int T = 1;
    cin >> T;
    while (T--) {
        solve();
    }
    return 0;
}

标签:cur,int,短路,37,Distributing,vector,Weights,100,dis
From: https://www.cnblogs.com/theophania/p/p37.html

相关文章

  • 力扣简2379 得到第k个黑块的最少涂色次数
    20230310每日一题滑动窗口题 classSolution{publicintminimumRecolors(Stringblocks,intk){intres=Integer.MAX_VALUE,len=blocks.length();......
  • 代码随想录算法Day37 | 738.单调递增的数字
    738.单调递增的数字题目链接:738.单调递增的数字-力扣(LeetCode)思路将数字转换成字符数组形式,然后从后向前遍历,当遇到当前这个数大于后一个数的时候,这个数减一,他的后一......
  • 查询性能: TDengine 最高达到了 InfluxDB 的 37 倍、 TimescaleDB 的 28.6 倍
    在上一篇文章《写入性能:TDengine最高达到InfluxDB的10.3倍,TimeScaleDB的6.74倍》中,我们基于TSBS 时序数据库(TimeSeriesDatabase)性能基准测试报告对三大数据库......
  • 2379. 得到 K 个黑块的最少涂色次数
    给你一个长度为n 下标从0 开始的字符串 blocks ,blocks[i] 要么是 'W' 要么是 'B' ,表示第 i 块的颜色。字符 'W'和 'B' 分别表示白色和黑色。给你一个整......
  • 力扣---2379. 得到 K 个黑块的最少涂色次数
    给你一个长度为n下标从0开始的字符串blocks,blocks[i]要么是'W'要么是'B',表示第i块的颜色。字符'W'和'B'分别表示白色和黑色。给你一个整数k,表示想要连......
  • P3378 【模板】堆
    P3378【模板】堆【模板】堆题目描述给定一个数列,初始为空,请支持下面三种操作:给定一个整数x,请将x加入到数列中。输出数列中最小的数。删除数列中最小的数(如果有......
  • P2375 [NOI2014] 动物园
    求num[i],表示1~i前缀的合法子串个数(满足前后缀相等,且不重合 #include<iostream>#include<cstring>usingnamespacestd;constintN=1e6+3,mod=1e9+7;......
  • LeetCode|372. 超级次方
    题目链接:超级次方发现自己算法比较弱,打算恶补一下常用算法,故最近开始刷LeetCode题目,初步定为每天一道。中等和困难会写解析,简单的不写,可以关注一下。你的任务是计算ab......
  • 四川九联代工M301H hi3798 mv300 mt7668魔百和 强刷和TTL线刷(救砖)经验分享
    四川九联代工M301Hhi3798mv300mt7668魔百和强刷和TTL线刷(救砖)经验分享 以下都是本次自己操作后的一些经验,不是技术分享,也是看来很多水教程后总结的精华。四川九......
  • [ABC237F] |LIS| = 3
    [ABC237F]|LIS|=3-洛谷|计算机科学教育新生态(luogu.com.cn)这道题的技巧性很强:考虑到最长上升子序列的长度只有3.我们令DP[长度][所有LIS=1最后一个元素的最小......