• D. Jzzhu and Cities


    传送门
    首先把题目给的边加入,然后对于火车来说,加入火车边有可能似的路径更短,所以说把火车的边也要加进去,那么最后看下起点到k个终点的路径的最短路是通过火车直达的还是通过其他边到达的就行了。
    就是这一步,如果说火车到达v点,而起点到v点的最短路小于火车的路径,就拆掉,如果等于路径,看一下到达这个点的最短路有几条,如果有大于1条的话,那么说明还有其他最短路可以到达,那么当前的火车就可以拆掉

    最短路计数,记录从起点到达这个点的路径个数

    if(dis[v] == dis[u] + e[i].w) num[v]++;
    else if(dis[v] > dis[u] + e[i].w) {
        num[v] = 1;
        dis[v] = dis[u] + e[i].w;
        q.push((Node){dis[v], v});
    }
    
    #include <iostream>
    #include <cstdio>
    #include <queue>
    #include <vector>
    #include <algorithm>
    using namespace std;
    #define ll long long
    const int N = 1e5 + 5;
    const int M = 5e5 + 5;
    const int INF = 0x3f3f3f3f;
    struct Edge{
        int to, next, w;
    }e[M << 1];
    int head[N], tot;
    void add(int u, int v, int w){
        e[++tot].to = v;
        e[tot].w = w;
        e[tot].next = head[u];
        head[u] = tot;
    }
    int dis[N], num[N];
    bool vis[N];
    struct Node{
        int dis, pos;
        bool operator < (const Node &b) const {
            return dis > b.dis;
        }
    };
    void Dijstra(int s, int n){
        for(int i = 1; i <= n; i++) dis[i] = INF;
        for(int i = 1; i <= n; i++) vis[i] = 0;
        dis[s] = 0;
        priority_queue<Node> q;
        q.push((Node){dis[s], s});
        while(!q.empty()) {
            Node temp = q.top(); q.pop();
            int u = temp.pos;
            if(vis[u]) continue;
            vis[u] = 1;
            for(int i = head[u]; i; i = e[i].next) {
                int v = e[i].to;
                if(dis[v] == dis[u] + e[i].w) num[v]++;
                else if(dis[v] > dis[u] + e[i].w) {
                    num[v] = 1;
                    dis[v] = dis[u] + e[i].w;
                    q.push((Node){dis[v], v});
                }
            }
        }
    }
    int main(){
        int n, m, k;
        scanf("%d%d%d", &n, &m, &k);
        for(int i = 1; i <= m; i++) {
            int u, v, w; scanf("%d%d%d", &u, &v, &w);
            add(u, v, w); add(v, u, w);
        }
        int ans = 0;
        Dijstra(1, n);
        vector<int> v1, v2;
        for(int i = 1; i <= k; i++) {
            int x, d;
            scanf("%d%d", &x, &d);
            v1.push_back(x); v2.push_back(d);
            add(1, x, d); add(x, 1, d);
        }
        Dijstra(1, n);
        for(int i = 0; i < k; i++) {
            int v = v1[i];
            int w = v2[i];
            if(dis[v] < w) ans++;
            else if(dis[v] == w) {
                if(num[v] > 1) {
                    ans++; num[v]--;
                }
            }
        }
        printf("%d
    ", ans);
        return 0;
    }
    
  • 相关阅读:
    题目3:爬楼梯
    题目1:删除排序数组中的重复数字
    最近目标
    软件工程----个人总结
    软件工程第二次作业——结对编程
    软件工程第一次作业补充
    爬楼梯
    买卖股票的最佳时机
    删除排序数组中的重复数字
    思考题
  • 原文地址:https://www.cnblogs.com/Emcikem/p/13955452.html
Copyright © 2020-2023  润新知