[CF449B] Jzzhu and Cities

Description

(n) 个点 (m) 条边的无向图,另有 (k) 条特殊边连接 (1-i),问最多删除多少条特殊边,使得每个点到 (1) 的最短距离不变。

Solution

考虑先计算到每个点的最短路条数,然后判断。

如果 (1 o i) 有特殊边,若特殊边长度 (>) 距离,那么显然这条特殊边没有贡献,直接删除。若等于距离,并且最短路条数 (>1),则删除这条特殊边,并将最短路条数 (-1)

注意这里 (-1) 以后我们并不需要去考虑它对其它的点的影响。

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

#define int long long
const int N = 1000005;
int n, m, k, d[N], h[N], spec[N][3], cnt[N], vis[N];

vector<pair<int, int>> g[N];
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> que;

void make(int u, int v, int w)
{
    g[u].push_back({v, w});
    g[v].push_back({u, w});
}

signed main()
{
    cin >> n >> m >> k;
    int t1, t2, t3;
    for (int i = 1; i <= m; i++)
    {
        cin >> t1 >> t2 >> t3;
        make(t1, t2, t3);
    }

    for(int i=1;i<=k;i++)
    {
        cin>>t1>>t2;
        make(1,t1,t2);
        spec[i][1]=t1;
        spec[i][2]=t2;
    }

    memset(d, 0x3f, sizeof d);
    d[1] = 0;
    que.push({0, 1});

    while (que.size())
    {
        int p = que.top().second;
        que.pop();
        if (vis[p] == 0)
        {
            vis[p] = 1;
            for (auto pr : g[p])
            {
                int q = pr.first, w = pr.second;
                if (d[q] == d[p] + w)
                    ++cnt[q];
                if (d[q] > d[p] + w)
                {
                    cnt[q] = 1;
                    d[q] = d[p] + w;
                    que.push({d[q], q});
                }
            }
        }
    }

    int ans = 0;
    for (int i = 1; i <= k; i++)
    {
        if (d[spec[i][1]] < spec[i][2])
            ++ans;
        else if (d[spec[i][1]] == spec[i][2] && cnt[spec[i][1]] > 1)
            ++ans, --cnt[spec[i][1]];
    }

    cout << ans << endl;
}
原文地址:https://www.cnblogs.com/mollnn/p/14095591.html