题目连接
题意
给你一个由n个点m条边组成的无向图,再给你k条边(起点必为1),再k条边中求最多能删掉几条边,使得1到各个点的最短路大小不变。
思路
Dijkstra 变形,dis数组初始化正无穷,可以直接用k条边先更新dis数组(因为起点必为1),然后将当前所有起点据终点长度不为正无穷的入队(1号点先入队),修改dijkstra中判断,如果当前点是第一次能够缩短,且不为正无穷说明铁路能够舍去。
代码
#include <bits/stdc++.h>
using namespace std;
#define _p pair<int, int>
const int N = 100005;
int n, m, k, ans = 0;
vector<_p> e[N];
int vis[N], dis[N], flag[N];
priority_queue<_p, vector<_p>, greater<_p> > q;
void dij()
{
while(!q.empty())
{
_p u = q.top();
q.pop();
if(vis[u.second]) continue;
vis[u.second] = 1;
for(auto v : e[u.second])
{
if(dis[v.second] >= dis[u.second]+v.first)
{
if(flag[v.second] == 0 && dis[v.second] != 0x3f3f3f3f) ++ans;
flag[v.second] = 1;
dis[v.second] = dis[u.second]+v.first;
q.push({dis[v.second], v.second});
}
}
}
}
int main() {
scanf("%d%d%d",&n,&m,&k);
while(m--)
{
int u, v, w;
scanf("%d%d%d",&u,&v,&w);
e[u].push_back({w,v});
e[v].push_back({w,u});
}
memset(vis,0,sizeof(vis));
memset(dis,0x3f,sizeof(dis));
for(int i = 1; i <= k; ++i) {
int v, w;
scanf("%d%d",&v,&w);
if(dis[v] != 0x3f3f3f3f) ++ans;
dis[v] = min(dis[v], w);
}
dis[1] = 0;
for(int i = 1; i <= n; ++i) if(dis[i] != 0x3f3f3f3f) q.push({dis[i], i});
dij();
printf("%d\n",ans);
return 0;
}