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條公路上的圖上修火車線路,那麼答案就可以轉化爲yy-必須要修的火車線路, ,,
  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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章