zoukankan      html  css  js  c++  java
  • 2019CCPC网络预选赛 1004 path 最短路

    题意:给你一张n个点m条边的有向图,问这张有向图的所有路径中第k短的路径长度是多少?n, m, k均为5e4级别。

    思路:前些日子有一场div3的F和这个题有点像,但是那个题要求的是最短路,并且k最大只有400。这个题的做法其实是一个套路(没见过QAQ)。

    首先把每个点的出边按边权从小到大排序,把每个点边权最小的那条边放入优先队列。对于优先队列中的每个点,记录一下这个点是从哪个点转移过来(last),转移过来的边对于last来说是第几小(rank)。这时,从当前点now选一条边权最小的边,形成新了路径放入队列。把last点的第k + 1小的边和last形成的新路径放入队列。第k次出队的路径就是第k短了路径。直观感受上是对的,证明的话纸上画画可能就出来了吧QAQ。

    代码:

    #include <bits/stdc++.h>
    #define LL long long
    #define pli pair<LL, int>
    #define pii pair<int, int>
    using namespace std;
    const int maxn = 100010;
    vector<pli> G[maxn];
    void add(int x, int y, long long z) {
        G[x].push_back(make_pair(z, y));
    }
    struct edge {
        int u, v;
    	LL w;
        bool operator < (const edge& rhs) const {
            return w < rhs.w;
        }
    };
    edge a[maxn];
    LL ans[maxn];
    int b[maxn];
    struct node {
    	int last, now, rank;
    	LL dis;
    	bool operator < (const node& rhs) const {
    		return dis > rhs.dis;
    	}
    };
    priority_queue<node> q;
    int main() {
        int T, n, m, t;
        scanf("%d", &T);
        while(T--) {
            while(q.size()) q.pop();
            scanf("%d%d%d", &n, &m, &t);
            for (int i = 1; i <= n; i++) G[i].clear();
            for (int i = 1; i <= m; i++) {
                scanf("%d%d%lld", &a[i].u, &a[i].v, &a[i].w);
                add(a[i].u, a[i].v, a[i].w);
            }
            int lim = 0;
            for (int i = 1; i <= t; i++){
                scanf("%d", &b[i]);
       			lim = max(lim, b[i]);
            }
            for (int i = 1; i <= n; i++) {
            	sort(G[i].begin(), G[i].end());
    		}
            for (int i = 1; i <= n; i++) {
            	if(G[i].size()) {
            		q.push((node){i, G[i][0].second, 0, G[i][0].first});
    			}
    		}
    		for (int i = 1; i <= lim; i++) {
    			node tmp = q.top();
    			q.pop();
    			ans[i] = tmp.dis;
    			if(G[tmp.now].size())
    				q.push((node){tmp.now, G[tmp.now][0].second, 0, tmp.dis + G[tmp.now][0].first});
    			if(G[tmp.last].size() > tmp.rank + 1) {
    				q.push((node){tmp.last, G[tmp.last][tmp.rank + 1].second, tmp.rank + 1, tmp.dis - G[tmp.last][tmp.rank].first + G[tmp.last][tmp.rank + 1].first});
    			}
    		}
    		for (int i = 1; i <= t; i++) {
    			printf("%lld
    ", ans[b[i]]);
    		}
        }
    }
    

      

  • 相关阅读:
    python装饰器执行机制
    蓝桥网试题 java 基础练习 十进制转十六进制
    蓝桥网试题 java 基础练习 十六进制转十进制
    蓝桥网试题 java 基础练习 十六进制转八进制
    蓝桥网试题 java 基础练习 数列排序
    蓝桥网试题 java 入门训练 A+B问题
    蓝桥网试题 java 入门训练 序列求和
    蓝桥网试题 java 入门训练 圆的面积
    蓝桥网试题 java 入门训练 Fibonacci数列
    贪心算法
  • 原文地址:https://www.cnblogs.com/pkgunboat/p/11401971.html
Copyright © 2011-2022 走看看