zoukankan      html  css  js  c++  java
  • CF449B最短路

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

    Sample test(s)
    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


    题意:有n座城市m条边,现在可以修k条铁路,城市1是首都,如果到第i座城市的最短路比修到这座城市的铁路的距离要长,就修铁路,
    问你有多少条铁路是没必要修的。
    思路:我们可以首先把首都到每座城市的距离用首都到每座城市的铁路距离表示,然后再用dijkstra算法+优先队列跑一次所有最短路,
    看看那条最短路改变了,如果改变了,就标记这个顶点。由于有重边,所以在输入铁路的时候要去重,取最短距离的铁路,其他的重边
    都是没必要修的,由于有的点是没有铁路的,所以要标记那些有铁路的点,好最后计数。


    代码:
    #include<cstdio>
    #include<cstring>
    #include<queue>
    #include<algorithm>
    #include<vector>
    using namespace std;
    //typedef __int64 LL;
    typedef long long LL;
    const int maxn = 100009;
    const int maxm = 300009;
    const LL inf = (LL)1<<40;
    
    struct node
    {
        int v,w;
        node(int v=0,int w=0):v(v),w(w){}
        bool operator < (const node a)const
        {
            return w > a.w;
        }
    };
    
    vector<node> eg[maxn];
    LL dis[maxn];
    int n;
    int vis[maxn];
    int used[maxn];
    
    void DIJ()
    {
        int i;
        memset(used,0,sizeof(used));
        priority_queue<node> pq;
        dis[1] = 0;
        for(i=1;i<=n;i++)
            pq.push(node(i,dis[i]));
        while(!pq.empty())
        {
            int u = pq.top().v;
            int w = pq.top().w;
            pq.pop();
            if(w > dis[u])continue;
            for(int i=0;i<eg[u].size();i++)
            {
                int v = eg[u][i].v;
                 w = eg[u][i].w;
                if(dis[v] > dis[u] + w)
                {
                    dis[v] = dis[u] + w;
                    used[v] = 1;   // 
                    pq.push(node(v,dis[v]));
                }else if(dis[v] == dis[u] + w)
                    used[v] = 1;
            }
            
        }
        
    }
    inline int min(int a,int b){return a < b ? a : b;}
    
    int main()
    {
        int m,k,i,a,b,c;
        while(~scanf("%d%d%d",&n,&m,&k))
        {
            for(i=0;i<=n;i++)
            {
                dis[i] = inf;
                eg[i].clear();
            }
            memset(vis,0,sizeof(vis));
            for(i=0;i<m;i++)
            {
                scanf("%d%d%d",&a,&b,&c);
                eg[a].push_back(node(b,c));
                eg[b].push_back(node(a,c));
            }
            int j = 0;
            int sum = 0;
            for(i=0;i<k;i++)
            {
                scanf("%d%d",&a,&b);
                if(!vis[a])
                {
                    vis[a] = 1;
                    dis[a] = b;
                }else
                {
                    sum ++;
                    dis[a] = min(dis[a],b);
                }
            }
            DIJ();
            for(i=1;i<=n;i++)
                if(vis[i] && used[i]) sum ++;
                printf("%d
    ",sum);
                
        }
        return 0;
    }
    
    /*
    
      
        5 5 3
        1 2 1
        2 3 2
        1 3 3
        3 4 4
        1 5 5
        3 5
        4 5
        5 5
        5 4 3
        1 2 999999999
        2 3 1000000000
        3 4 529529529
        5 1 524524524
        5 524444444
        5 529999999
        2 1000000000
        2 2 3
        1 2 2
        2 1 3
        2 1
        2 2
        2 3
        
          
            
    */
  • 相关阅读:
    Azure 虚拟机诊断设置问题排查
    虚拟机压力测试延迟高的可能原因及 ILPIP 配置 / 查询脚本
    理解 Azure 平台中虚拟机的计算能力
    如何复制或导出托管磁盘
    理解托管磁盘的原理与优势
    Azure 托管镜像和非托管镜像对比
    如何将同一云服务下的虚拟机从经典部署模型迁移到 Azure Resource Manager
    如何将同一 VNET 下的虚拟机从经典部署模型迁移到 Azure Resource Manager
    如何将使用托管磁盘虚拟机的 OS 盘挂载到其他虚拟机上
    基于 Azure 托管磁盘配置高可用共享文件系统
  • 原文地址:https://www.cnblogs.com/BruceNoOne/p/3886692.html
Copyright © 2011-2022 走看看