2019CCPC网络预选赛 1004 path 最短路

Posted pkgunboat

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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\n", ans[b[i]]);
		
    

  

以上是关于2019CCPC网络预选赛 1004 path 最短路的主要内容,如果未能解决你的问题,请参考以下文章

2019CCPC网络预选赛 1003 K-th occurrence 后缀自动机 + 二分 + 主席树

2019中国大学生程序设计竞赛(CCPC) - 网络选拔赛

2019 CCPC - 网络选拔赛 D path(求第k短路)

2018CCPC网络赛 1004Find Integer(勾股数+费马大定理)

2018 CCPC网络赛1004 - 费马大定理&数学

又是一年末