CF499B·Jzzhu and Cities

初见安~这里是传送门:CF #257 Div1 B Jzzhu and Cities

Description

Jzzhu is the president of country A. There are n cities numbered from 1 to n in his country. City 1 is the capital of A. Also there are mroads connecting the cities. One can go from city ui to vi (and vise versa) using the i-th road, the length of this road is xi. Finally, there are k train routes in the country. One can use the i-th train route to go from capital of the country to city si (and vise versa), the length of this route is yi.

Jzzhu doesn't want to waste the money of the country, so he is going to close some of the train routes. Please tell Jzzhu the maximum number of the train routes which can be closed under the following condition: the length of the shortest path from every city to the capital mustn't change.

Input

The first line contains three integers n, m, k (2 ≤ n ≤ 105; 1 ≤ m ≤ 3·105; 1 ≤ k ≤ 105).

Each of the next m lines contains three integers ui, vi, xi (1 ≤ ui, vi ≤ nui ≠ vi; 1 ≤ xi ≤ 109).

Each of the next k lines contains two integers si and yi (2 ≤ si ≤ n; 1 ≤ yi ≤ 109).

It is guaranteed that there is at least one way from every city to the capital. Note, that there can be multiple roads between two cities. Also, there can be multiple routes going to the same city from the capital.

Output

Output a single integer representing the maximum number of the train routes which can be closed.

input

5 5 3
1 2 1
2 3 2
1 3 3
3 4 4
1 5 5
3 5
4 5
5 5

output

2

input

2 2 3
1 2 2
2 1 3
2 1
2 2
2 3

output

2

Sol

这个题很有意思啊……说白了就是给你一个n个点m条边的无向图,有k条特殊的边,问你最多能删去多少条特殊边并保证每个点到第一个点的最短路长度不变

一开始我的思路很简单——这不就是一个最短路径树嘛!【良心链接:其实和这个题没有多大关系……想了解的话欢迎orz

也就是说直接处理出每个点的最短路,并且尽量不用特殊路径不就行了吗!!

结果后期思路就打岔了。就想到什么二维……【混乱】以至于被lty大佬嘲笑了……

正解就是上文说的那样。跑一遍最短路就可以了。期间判断:如果可以更短,那就直接更新并且是否必经特殊路线的标记就是这条边的标记;否则,如果出现了多条最短路,那么只要是能不用走必经边的就都标记为不用走了。

不用考虑过于长远,只考虑该点以及对于与其相连的必经边是否需要。

上代码——

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<queue>
#define maxm 400005
#define maxn 100005
using namespace std;
typedef long long ll;
int read() {
	int x = 0, f = 1, ch = getchar();
	while(!isdigit(ch)) {if(ch == '-') f = -1; ch = getchar();}
	while(isdigit(ch)) x = (x << 1) + (x << 3) + ch - '0', ch = getchar();
	return x * f;
}
 
struct edge {
	int to, w, nxt;
	bool flag;//标记该边是否为特殊边
	edge() {}
	edge(int t, int ww, bool op, int n) {to = t, w = ww, flag = op, nxt = n;}
}e[maxm << 1];
 
int head[maxn], k = 0;
void add(int u, int v, int w, bool op) {e[k] = edge(v, w, op, head[u]); head[u] = k++;}
 
int n, m, K;
bool must[maxn], vis[maxn];
ll dis[maxn];
void dij() {
	priority_queue<pair<int, int> > q; q.push(make_pair(0, 1));//一定要用优先队列优化
	memset(dis, 0x3f, sizeof dis); dis[1] = 0;
	while(q.size()) {
		register int u = q.top().second; q.pop();
		if(vis[u]) continue;
		vis[u] = true;//这里的vis数组很重要
		for(int i = head[u]; ~i; i = e[i].nxt) {
			register int v = e[i].to;
			if(dis[u] + e[i].w < dis[v]) {//如果更短,直接标记
				dis[v] = dis[u] + e[i].w, must[v] = e[i].flag;
				q.push(make_pair(-dis[v], v));
			}
			
			else if(dis[u] + e[i].w == dis[v] && !e[i].flag) {//如果不用走必经边,那同样优秀
				must[v] = 0;
			}
		}
	}
}
 
signed main() {
	memset(head, -1, sizeof head);
	n = read(), m = read(), K = read();
	for(int u, v, w, i = 1; i <= m; i++) u = read(), v = read(), w = read(), add(u, v, w, 0), add(v, u, w, 0);//0是非特殊边
	
	for(int w, v, i = 1; i <= K; i++) v = read(), w = read(), add(1, v, w, 1);
	//1是特殊边
	dij();
	
	int ans = K;
	for(int i = 1; i <= n; i++) if(must[i]) ans--;//如果到这个点的最短路必经特殊边
	printf("%d\n", ans);
}
 

迎评:)
——End——

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值