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;
}