B. Jzzhu and Cities(最短路+统计到某个最短路方案数)

B. Jzzhu and Cities

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 ≤ n; ui ≠ 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
Examples

inputCopy
5 5 3
1 2 1
2 3 2
1 3 3
3 4 4
1 5 5
3 5
4 5
5 5
outputCopy
2
inputCopy
2 2 3
1 2 2
2 1 3
2 1
2 2
2 3
outputCopy
2

思路

  • 题意:给我们一个无向图,有n个节点,x条路,y条火车线路,在所有的火车线路中所有的节点都是从节点一开始的路线,问我最多可以拆掉多少条火车线路,但是拆掉的火车线路不能影响原来1 到其他各个节点的最短路的距离

  • 思路:

  1. 对于拆火车线路,我们可以看成在只有x条公路上的图上修火车线路,那么答案就可以转化为 y 线 y-必须要修的火车线路 , ,,
  2. 对于修火车线路:首先从1 到某个节点的火车线路如果有多条的话,我们可能就只需要修多条线路中最短的那一条(可这一条也不必修,因为有其他的短路可以到达),这样我们建好图之后,我们就跑做短路看1 到某个节点的最短路方案数有几条,如果有多条并且1到这个节点我们修建路火车线路,那么我们就可把这一条拆出了,如果之后一条路径,无论这一条路是否是我们自己建造的火车线路都没发拆除。
    3.最后注意一下到某个最短点路径统计方案数到统计方法
    我可以先int一个pre【】数组,初始化pre[1] = 1(刚开始到1这个点的方案数为1),那么当由节点1 到节点2的时候,那么2的最短的方案数就是1的最短路的方案数,假设这个时候还有一个点3,它转移到2节点的距离也与最短路距离相同那么我们直接 将原来到2点方案数加上最短路到3的方案数就是总的方案数了

代码


#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<map>
#include<vector>
#include<queue>
#include<stack>
void fre() { freopen("A.txt","r",stdin); freopen("Ans.txt","w",stdout); }
using namespace std;

#define INF 0x3f3f3f3f
const int mxn = 4e5;
int n, m, k;
int head[mxn], mp[mxn], dis[mxn], num[mxn];
struct Edge
{
    int v, w, next;
} edge[mxn*2];
int l = 0;

void Add(int u, int v, int w)
{
    edge[++ l] = (Edge){ v, w, head[u] };
    head[u] = l;
}
int use[mxn];
void Spfa(int s)
{
    for(int i = 0; i <= n; i ++)
        dis[i] = INF;
    dis[s] = 0;
    priority_queue<int> q;
    q.push(s);
    num[1] = 1;
    int u, v, w;
    while(! q.empty())
    {
        u = q.top(); q.pop();
        use[u] = 0;
        
        for(int i = head[u]; i; i = edge[i].next)
        {
            v = edge[i].v;
            w = edge[i].w;
            if(dis[v] > dis[u] + w)
            {
                dis[v] = dis[u] + w;
                num[v] = num[u];
                if(! use[v])
                {
                    q.push(v);
                    use[v] = 1;
                }
            }
            else if(dis[v] == dis[u] + w)
            {
                num[v] += num[u];
            }
        }
    }
}

int main()
{
    /* fre(); */
    scanf("%d %d %d", &n, &m, &k);
    int u, v, w;
    for(int i = 0; i < m; i ++)
    {
        scanf("%d %d %d", &u, &v, &w);
        Add(u, v, w);
        Add(v, u, w);
    }
    int cnt = 0;
    for(int i = 0; i < k; i ++)
    {
        scanf("%d %d", &v, &w);
        if(mp[v] ==0 || mp[v] > w)
            mp[v] = w;
    }

    for(int i = 1; i <= n; i ++)
    {
        if(mp[i])
        {
            cnt ++;
            Add(1, i, mp[i]);
            Add(i, 1, mp[i]);
        }
    }

    Spfa(1);
    
    for(int i = 1; i <= n; i ++)
    {
        /* printf("dis[%d] = %d, num = %d\n", i, dis[i], num[i]); */
        if(mp[i])
        {
            if(mp[i] > dis[i])
                cnt --;
            else if(mp[i] == dis[i] && num[i] > 1)
                cnt --;
        }
    }
    printf("%d\n", k - cnt);

    return 0;
}
发布了194 篇原创文章 · 获赞 268 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/qq_34261446/article/details/105633191
今日推荐