codeforces 449B Jzzhu and Cities(最短路)

B. Jzzhu and Cities

time limit per test

2 seconds

memory limit per test

256 megabytes

input

standard input

output

standard output

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 m roads 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.

Examples

input

Copy

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

Copy

2

input

Copy

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

output

Copy

2

题目大意:有m条普通道路,k条火车道路,给出m条道路的信息,再给出k条火车路的信息,火车路表示从1点到某点的距离,问保证最短路的前提下,最多能去除多少条火车路

先跑一遍最短路,得到1到每个点的最短路距离,当最短路要更新的时候,就把这个点上的最短路记为1,如果等于的话,就+1,最后对k条边进行判断即可

用SPFA会超时..

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int maxn=1e5+7;
const int maxm=4e5+7;
const int inf=0x3f3f3f3f;
typedef pair<int,int> P;
struct Node
{
    int to;
    int val;
    int next;
}edge[maxm<<1];
struct LDJ
{
    int to;
    int val;
}num[maxm];
int cnt;
int head[maxn];
int train[maxn];
int dis[maxn];
bool vis[maxn];
int road_cnt[maxn];
void init()
{
    memset(head,-1,sizeof(head));
    memset(road_cnt,0,sizeof(road_cnt));
    cnt=0;
    return;
}
void add(int u,int v,int val)
{
    edge[cnt].to=v;
    edge[cnt].val=val;
    edge[cnt].next=head[u];
    head[u]=cnt++;
    edge[cnt].to=u;
    edge[cnt].val=val;
    edge[cnt].next=head[v];
    head[v]=cnt++;
    return;
}
void spfa()
{
    memset(dis,inf,sizeof(dis));
    memset(vis,false,sizeof(vis));
    dis[1]=0;
    vis[1]=true;
    queue<int> que;
    que.push(1);
    while(!que.empty())
    {
        int node=que.front();
        que.pop();
        vis[node]=false;
        for(int i=head[node];~i;i=edge[i].next)
        {
            int v=edge[i].to;
            if(dis[v]>dis[node]+edge[i].val)
            {
                dis[v]=dis[node]+edge[i].val;
                road_cnt[v]=1;
                if(!vis[v])
                {
                    vis[v]=true;
                    que.push(v);
                }
            }
            else if(dis[v]==dis[node]+edge[i].val)
            {
                road_cnt[v]++;
            }
        }
    }
    return;
}
void dijkstra()
{
    memset(dis,inf,sizeof(dis));
    memset(vis,false,sizeof(vis));
    priority_queue<P,vector<P>,greater<P> > que;
    dis[1]=0;
    que.push(make_pair(dis[1],1));
    while(!que.empty())
    {
        P now=que.top();
        que.pop();
        int node=now.second;
        if(vis[node]) continue;
        vis[node]=true;
        for(int i=head[node];~i;i=edge[i].next)
        {
            int v=edge[i].to;
            if(!vis[v]&&dis[v]>dis[node]+edge[i].val)
            {
                dis[v]=dis[node]+edge[i].val;
                road_cnt[v]=1;
                que.push(make_pair(dis[v],v));
            }
            else if(dis[v]==dis[node]+edge[i].val)
            {
                road_cnt[v]++;
            }
        }
    }
    return;
}
int main()
{
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    int n,m,k;
    while(~scanf("%d%d%d",&n,&m,&k))
    {
        init();
        for(int i=0;i<m;i++)
        {
            int u,v,w;
            scanf("%d%d%d",&u,&v,&w);
            add(u,v,w);
        }
        for(int i=0;i<k;i++)
        {
            scanf("%d%d",&num[i].to,&num[i].val);
            add(1,num[i].to,num[i].val);
        }
        //spfa();
        dijkstra();
        int ans=0;
        for(int i=0;i<k;i++)
        {
            if(dis[num[i].to]<num[i].val)
            {
                ans++;
            }
            else if(dis[num[i].to]==num[i].val)
            {
                if(road_cnt[num[i].to]>1)
                {
                    ans++;
                    road_cnt[num[i].to]--;
                }
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值