- 题目链接:http://codeforces.com/contest/450/problem/D
- 题意:给n个城市、m条公路、k条铁路(铁路只在1号城市与其他城市间)。算出在最短路不变的情况下,最多能去除多少条铁路
- 算法:最短路 dijkstra
- 思路:
- 先把m个公路建图,这样边数达到2*m, 在对k 个铁路建图,进而可以判断边为公路还是铁路。当最短路是公路时,令flag=1; 当最短路为铁路时,令flag=0。当公路、铁路都最短时,令flag=0;
- 遍历所有城市,当flag==1时说明连在这个点需要连一条铁路,并将剩余铁路去除;当flag==0时,说明这个点不需要铁路,并将这个点上所有铁路去除。
- 坑点
- 有些城市之间只有铁路,没有公路
- dijkstra 松弛时只有dis[e.v] > dis[v] + e.w 时才会 对dis[e.v]赋值,使得无法在公路dis和铁路dis相等时进行标记,而需要另用一个if判断相等
#include <bits/stdc++.h>
#define pi acos(-1)
using namespace std;
typedef long long LL;
const LL INF = 0x3f3f3f3f;
const LL ll_INF = 0x3f3f3f3f3f3f3f3f;
const LL maxn = 300100;
const int mod = 1000000007;
typedef pair<LL, LL> P;
priority_queue<P,vector<P>,greater<P> > que;
struct Edge{ LL v, w, next; } es[3*maxn];
LL head[maxn];
LL tr[maxn];
LL flag[maxn];
LL n, m, u, v, w, s, t, cnt, dis[maxn];
void add(LL u, LL v, LL w)
{
es[cnt].v = v;
es[cnt].w = w;
es[cnt].next = head[u];
head[u] = cnt++;
}
void dijkstra()
{
P p;
Edge e;
LL v;
fill(dis, dis+maxn, ll_INF);
memset(flag, 0, sizeof(flag));
dis[s] = 0;
que.push(P(0, s));
while(!que.empty()){
p = que.top(); que.pop();
v = p.second;
if(dis[v] < p.first)
continue;
for(LL i=head[v]; i!=-1LL; i=e.next){
e = es[i];
if(dis[e.v] > dis[v] + e.w){
dis[e.v] = dis[v] + e.w;
que.push(P(dis[e.v], e.v));
if(i>=2*m) flag[e.v]=1;
else flag[e.v]=0;
}
else if((dis[e.v] == dis[v] + e.w) && i<2*m ) flag[e.v]=0;
}
}
}
int main()
{
LL k;
scanf("%I64d%I64d%I64d", &n, &m, &k);
cnt=0;
memset(head, -1LL, sizeof(head));
memset(tr, 0, sizeof(tr));
for(LL i=0; i<m; i++){
scanf("%I64d%I64d%I64d", &u, &v, &w);
add(u, v, w);
add(v, u, w);
}
s=1;
LL a, b, ans=0;
for(LL i=0; i<k; i++){
scanf("%I64d%I64d", &a, &b);
add(s, a, b);
add(a, s, b);
tr[a]++;
}
dijkstra();
for(LL i=1; i<=n; i++){
if(flag[i]==1) ans+=tr[i]-1;
else ans+=tr[i];
}
printf("%I64d\n", ans);
}