[CF507E] Breaking Good - 最短路

Description

在一个有 n 个城市 m 条道路的国家,有一个犯罪团伙要去抢劫银行,银行在城市 1,犯罪团伙在城市 n,任务是在城市 1 和城市 n 之间选择一个最短路径,当有多个最短路径的时候选择影响值最小的,为 0 的道路是指未工作的,为 1 的道路是指修好的,在选择好最短路径后,要修复好最短路径上未工作的路,破坏其他路径上工作的路径

Solution

梳理一下题意,影响 = 修复 + 破坏 = 最短路长 - 最短路上工作路数 + 工作总道路数 - 最短路上工作路数 = 最短路长 + 工作总道路数 - 2 最短路上工作道路数

要最小化影响值,首先要求最短路,然后要选择最短路上工作道路数最多的

#include <bits/stdc++.h>
using namespace std;

#define int long long
const int N = 1000005;

struct num
{
    int dist;
    int sum;

    num(int dist = 1e18, int sum = 0) : dist(dist), sum(sum)
    {
    }

    num operator+(const num &rhs) const
    {
        return num(dist + rhs.dist, sum + rhs.sum);
    }

    bool operator<(const num &rhs) const
    {
        if (dist == rhs.dist)
            return sum > rhs.sum;
        return dist < rhs.dist;
    }
};

int n, m;
vector<pair<int, int>> g[N];
num f[N];
int v[N], from[N][3];

signed main()
{
    ios::sync_with_stdio(false);

    cin >> n >> m;
    vector<tuple<int, int, int>> src;
    for (int i = 1; i <= m; i++)
    {
        int t1, t2, t3;
        cin >> t1 >> t2 >> t3;
        src.push_back(make_tuple(t1, t2, t3));
        g[t1].push_back({t2, t3});
        g[t2].push_back({t1, t3});
    }

    queue<int> que;
    que.push(1);
    f[1] = num(0, 0);
    v[1] = 1;

    while (que.size())
    {
        auto p = que.front();
        que.pop();
        for (auto [q, w] : g[p])
        {
            if (f[p] + num(1, w) < f[q])
            {
                f[q] = f[p] + num(1, w);
                from[q][0] = p;
                from[q][1] = q;
                from[q][2] = w;
                if (v[q] == 0)
                {
                    que.push(q);
                    v[q] = 1;
                }
            }
        }
    }

    map<pair<int, int>, int> mp;
    vector<tuple<int, int, int>> ans;
    int p = n;
    while (p > 1)
    {
        mp[{from[p][0], from[p][1]}] = mp[{from[p][1], from[p][0]}] = 1;
        p = from[p][0];
    }

    for (auto [x, y, z] : src)
    {
        if (mp[{x, y}])
        {
            if (z == 0)
                ans.push_back(make_tuple(x, y, z ^ 1));
        }
        else
        {
            if (z == 1)
                ans.push_back(make_tuple(x, y, z ^ 1));
        }
    }

    cout << ans.size() << endl;
    if (ans.size() == 0)
        return 0;
    for (int i = ans.size() - 1; i >= 0; i--)
    {
        auto [x, y, z] = ans[i];
        cout << x << " " << y << " " << z << endl;
    }
}

相关文章:

猜你喜欢
  • 2021-08-06
  • 2021-08-05
  • 2022-02-10
  • 2022-12-23
  • 2022-01-10
  • 2021-11-02
  • 2021-09-25
相关资源
相似解决方案